Add a JS test for the clin-fields Vue component.
In order to do this, it was expedient to move the CLINFields Jinja macro into its own file and pass in all the data it requires.
This commit is contained in:
parent
526dc94455
commit
7ea1ae5a34
48
js/components/__tests__/clin_fields.test.js
Normal file
48
js/components/__tests__/clin_fields.test.js
Normal file
@ -0,0 +1,48 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
|
||||
import clinFields from '../clin_fields'
|
||||
|
||||
import { makeTestWrapper } from '../../test_utils/component_test_helpers'
|
||||
|
||||
const ClinFieldsWrapper = makeTestWrapper({
|
||||
components: { clinFields },
|
||||
templatePath: 'clin_fields.html',
|
||||
})
|
||||
|
||||
describe('ClinFields Test', () => {
|
||||
it('should calculate the percentage of obligated funds', () => {
|
||||
const wrapper = mount(ClinFieldsWrapper, {
|
||||
propsData: {
|
||||
initialData: {},
|
||||
},
|
||||
})
|
||||
const percentObligatedElement = wrapper.find('#percent-obligated')
|
||||
// test starts at zero
|
||||
expect(percentObligatedElement.text()).toBe('0%')
|
||||
|
||||
// test greater than 100%
|
||||
wrapper.find('input#obligated_amount').setValue('2')
|
||||
wrapper.find('input#total_amount').setValue('1')
|
||||
expect(percentObligatedElement.text()).toBe('>100%')
|
||||
|
||||
// test greater than 99% but less than 100%
|
||||
wrapper.find('input#obligated_amount').setValue('999')
|
||||
wrapper.find('input#total_amount').setValue('1000')
|
||||
expect(percentObligatedElement.text()).toBe('>99%')
|
||||
|
||||
// test a normal percentage
|
||||
wrapper.find('input#obligated_amount').setValue('1')
|
||||
wrapper.find('input#total_amount').setValue('2')
|
||||
expect(percentObligatedElement.text()).toBe('50%')
|
||||
|
||||
// test less than 1%
|
||||
wrapper.find('input#obligated_amount').setValue('1')
|
||||
wrapper.find('input#total_amount').setValue('1000')
|
||||
expect(percentObligatedElement.text()).toBe('<1%')
|
||||
|
||||
// test resets to zero
|
||||
wrapper.find('input#obligated_amount').setValue('0')
|
||||
wrapper.find('input#total_amount').setValue('0')
|
||||
expect(percentObligatedElement.text()).toBe('0%')
|
||||
})
|
||||
})
|
571
js/test_templates/clin_fields.html
Normal file
571
js/test_templates/clin_fields.html
Normal file
@ -0,0 +1,571 @@
|
||||
|
||||
<clin-fields
|
||||
|
||||
v-bind:initial-clin-index='0'
|
||||
v-bind:initial-total='0'
|
||||
v-bind:initial-obligated='0'
|
||||
v-bind:initial-start-date="'None'"
|
||||
v-bind:initial-end-date="'None'"
|
||||
v-bind:initial-clin-number="'None'"
|
||||
|
||||
v-bind:contract-start="'2019-09-14'"
|
||||
v-bind:contract-end="'2022-09-14'"
|
||||
inline-template>
|
||||
<div class="clin-card" v-if="showClin">
|
||||
<div class="card__title">
|
||||
<span class="h4" v-html='clinTitle'></span>
|
||||
<button
|
||||
v-if='$parent.clinIndex > 0'
|
||||
class="icon-link icon-link__remove-clin"
|
||||
v-on:click="openModal(removeModalId)"
|
||||
type="button">
|
||||
|
||||
<span class="icon icon--x " aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M2 2l12 12M14 15c-.256 0-.512-.098-.707-.293l-12-12c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l12 12c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293zm0-13L2 14"/><path d="M2 15c-.256 0-.512-.098-.707-.293-.391-.391-.391-1.023 0-1.414l12-12c.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414l-12 12C2.512 14.902 2.256 15 2 15z"/></svg>
|
||||
</span>
|
||||
|
||||
</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
CLIN Details
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
|
||||
<textinput
|
||||
v-cloak
|
||||
name='number'
|
||||
validation='anything'
|
||||
|
||||
|
||||
|
||||
|
||||
v-bind:optional=false
|
||||
key='number'
|
||||
:watch='true'
|
||||
inline-template>
|
||||
|
||||
<div
|
||||
class=' '
|
||||
v-bind:class="['usa-input usa-input--validation--' + validation, { 'usa-input--error': showError, 'usa-input--success': showValid, 'usa-input--validation--paragraph': paragraph, 'no-max-width': noMaxWidth }]">
|
||||
|
||||
|
||||
<label for=number>
|
||||
<div class="usa-input__title">
|
||||
CLIN
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<span v-show='showError'>
|
||||
<span class="icon icon--alert icon-validation" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#fdb81e">
|
||||
<path d="M8 16c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zM8 2C4.691 2 2 4.691 2 8s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 8c-.552 0-1-.447-1-1V4c0-.552.448-1 1-1s1 .448 1 1v5c0 .553-.448 1-1 1zm0 3c-.26 0-.52-.11-.71-.29-.18-.19-.29-.45-.29-.71 0-.271.11-.521.29-.71.38-.37 1.05-.37 1.42 0 .18.189.29.45.29.71s-.11.52-.29.71c-.19.18-.45.29-.71.29z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span v-show='showValid'>
|
||||
<span class="icon icon--ok icon-validation" aria-hidden="true"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg></span>
|
||||
</span>
|
||||
|
||||
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
|
||||
<masked-input
|
||||
v-on:input='onInput'
|
||||
v-on:blur='onBlur'
|
||||
v-on:change='onChange'
|
||||
v-bind:value='value'
|
||||
v-bind:mask='mask'
|
||||
v-bind:pipe='pipe'
|
||||
v-bind:keep-char-positions='keepCharPositions'
|
||||
v-bind:aria-invalid='showError'
|
||||
type='text'
|
||||
|
||||
id='number'
|
||||
|
||||
ref='input'
|
||||
placeholder=''>
|
||||
</masked-input>
|
||||
|
||||
|
||||
|
||||
<input
|
||||
type='hidden'
|
||||
v-bind:value='rawValue'
|
||||
|
||||
name='number'
|
||||
|
||||
/>
|
||||
|
||||
|
||||
<template v-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class='usa-input__message'></span>
|
||||
</template>
|
||||
|
||||
|
||||
</div>
|
||||
</textinput>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
|
||||
<optionsinput
|
||||
name='jedi_clin_type'
|
||||
inline-template
|
||||
|
||||
|
||||
key='jedi_clin_type'
|
||||
v-bind:watch='true'
|
||||
v-bind:optional=false
|
||||
v-bind:null-option="'None'"
|
||||
>
|
||||
<div
|
||||
v-bind:class="['usa-input', { 'usa-input--error': showError, 'usa-input--success': showValid }]">
|
||||
|
||||
<fieldset data-ally-disabled="true" v-on:change="onInput" class="usa-input__choices ">
|
||||
|
||||
<legend>
|
||||
<div class="usa-input__title-inline">
|
||||
Corresponding IDIQ CLIN
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</legend>
|
||||
|
||||
|
||||
<select id="jedi_clin_type" name="jedi_clin_type"><option value="JEDI_CLIN_1">IaaS/PaaS (IDIQ CLIN 0001)</option><option value="JEDI_CLIN_2">IDIQ CLIN 0002</option><option value="JEDI_CLIN_3">IDIQ CLIN 0003</option><option value="JEDI_CLIN_4">IDIQ CLIN 0004</option></select>
|
||||
|
||||
<template v-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
</optionsinput>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
CLIN Funding
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<clindollaramount
|
||||
v-cloak
|
||||
inline-template
|
||||
|
||||
:funding-valid='true'
|
||||
|
||||
|
||||
name='total_amount'
|
||||
|
||||
|
||||
key='total_amount'
|
||||
|
||||
|
||||
validation="clinDollars"
|
||||
:watch='true'>
|
||||
<div v-bind:class="['usa-input usa-input--validation--dollars', { 'usa-input--error': showFundingError, 'usa-input--success': showFundingValid}]">
|
||||
|
||||
<label for='total_amount'>
|
||||
|
||||
|
||||
|
||||
<div class="usa-input__title">Total CLIN Value</div>
|
||||
|
||||
<span v-show='showFundingError'>
|
||||
<span class="icon icon--alert icon-validation" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#fdb81e">
|
||||
<path d="M8 16c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zM8 2C4.691 2 2 4.691 2 8s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 8c-.552 0-1-.447-1-1V4c0-.552.448-1 1-1s1 .448 1 1v5c0 .553-.448 1-1 1zm0 3c-.26 0-.52-.11-.71-.29-.18-.19-.29-.45-.29-.71 0-.271.11-.521.29-.71.38-.37 1.05-.37 1.42 0 .18.189.29.45.29.71s-.11.52-.29.71c-.19.18-.45.29-.71.29z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span v-show='showFundingValid'>
|
||||
<span class="icon icon--ok icon-validation" aria-hidden="true"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg></span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<masked-input
|
||||
v-on:input='onInput'
|
||||
v-on:blur='onBlur'
|
||||
v-on:change='onChange'
|
||||
v-bind:value='value'
|
||||
v-bind:mask='mask'
|
||||
v-bind:pipe='pipe'
|
||||
v-bind:keep-char-positions='keepCharPositions'
|
||||
v-bind:aria-invalid='showError'
|
||||
type='text'
|
||||
:id='name'
|
||||
ref='input'>
|
||||
</masked-input>
|
||||
|
||||
<input type='hidden' v-bind:value='rawValue' :name='name' />
|
||||
<template v-if='!fundingValid'>
|
||||
<span class='usa-input__message'>Obligated amount must be less than or equal to total amount</span>
|
||||
</template>
|
||||
<template v-else-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class='usa-input__message'></span>
|
||||
</template>
|
||||
</div>
|
||||
</clindollaramount>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<clindollaramount
|
||||
v-cloak
|
||||
inline-template
|
||||
|
||||
:funding-valid='fundingValid'
|
||||
|
||||
|
||||
name='obligated_amount'
|
||||
|
||||
|
||||
key='obligated_amount'
|
||||
|
||||
|
||||
validation="clinDollars"
|
||||
:watch='true'>
|
||||
<div v-bind:class="['usa-input usa-input--validation--dollars', { 'usa-input--error': showFundingError, 'usa-input--success': showFundingValid}]">
|
||||
|
||||
<label for='obligated_amount'>
|
||||
|
||||
|
||||
|
||||
<div class="usa-input__title">Obligated Funds</div>
|
||||
|
||||
<span v-show='showFundingError'>
|
||||
<span class="icon icon--alert icon-validation" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#fdb81e">
|
||||
<path d="M8 16c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zM8 2C4.691 2 2 4.691 2 8s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 8c-.552 0-1-.447-1-1V4c0-.552.448-1 1-1s1 .448 1 1v5c0 .553-.448 1-1 1zm0 3c-.26 0-.52-.11-.71-.29-.18-.19-.29-.45-.29-.71 0-.271.11-.521.29-.71.38-.37 1.05-.37 1.42 0 .18.189.29.45.29.71s-.11.52-.29.71c-.19.18-.45.29-.71.29z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span v-show='showFundingValid'>
|
||||
<span class="icon icon--ok icon-validation" aria-hidden="true"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg></span>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<masked-input
|
||||
v-on:input='onInput'
|
||||
v-on:blur='onBlur'
|
||||
v-on:change='onChange'
|
||||
v-bind:value='value'
|
||||
v-bind:mask='mask'
|
||||
v-bind:pipe='pipe'
|
||||
v-bind:keep-char-positions='keepCharPositions'
|
||||
v-bind:aria-invalid='showError'
|
||||
type='text'
|
||||
:id='name'
|
||||
ref='input'>
|
||||
</masked-input>
|
||||
|
||||
<input type='hidden' v-bind:value='rawValue' :name='name' />
|
||||
<template v-if='!fundingValid'>
|
||||
<span class='usa-input__message'>Obligated amount must be less than or equal to total amount</span>
|
||||
</template>
|
||||
<template v-else-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class='usa-input__message'></span>
|
||||
</template>
|
||||
</div>
|
||||
</clindollaramount>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="h5 clin-card__title">Percent Obligated</div>
|
||||
<p id="percent-obligated" v-html='percentObligated'></p>
|
||||
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
Period of Performance
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector
|
||||
|
||||
|
||||
name-tag='start_date'
|
||||
initialmonth=""
|
||||
initialday=""
|
||||
initialyear=""
|
||||
v-bind:watch='true'
|
||||
:optional='false'
|
||||
inline-template>
|
||||
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
Start Date
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<p class='usa-input__help'>
|
||||
For example: 07 04 1776
|
||||
</p>
|
||||
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input name="start_date" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>Month</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>Day</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>Year</label>
|
||||
<input
|
||||
id="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
|
||||
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="showValidation">
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
|
||||
<span class="icon icon--ok icon--green" aria-hidden="true"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg></span>
|
||||
|
||||
</div>
|
||||
<div class="usa-form-group-date-ok" v-else>
|
||||
|
||||
<span class="icon icon--alert icon--red" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#fdb81e">
|
||||
<path d="M8 16c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zM8 2C4.691 2 2 4.691 2 8s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 8c-.552 0-1-.447-1-1V4c0-.552.448-1 1-1s1 .448 1 1v5c0 .553-.448 1-1 1zm0 3c-.26 0-.52-.11-.71-.29-.18-.19-.29-.45-.29-.71 0-.271.11-.521.29-.71.38-.37 1.05-.37 1.42 0 .18.189.29.45.29.71s-.11.52-.29.71c-.19.18-.45.29-.71.29z"/>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector
|
||||
|
||||
|
||||
name-tag='end_date'
|
||||
initialmonth=""
|
||||
initialday=""
|
||||
initialyear=""
|
||||
v-bind:watch='true'
|
||||
:optional='false'
|
||||
inline-template>
|
||||
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
End Date
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class='usa-alert usa-alert-info' role='alert' aria-live='polite'>
|
||||
|
||||
<div class='usa-alert-body'>
|
||||
|
||||
|
||||
|
||||
<p class='usa-alert-text'>
|
||||
A CLIN's period of performance must end before September 14, 2022.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<p class='usa-input__help'>
|
||||
For example: 07 04 1776
|
||||
</p>
|
||||
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input name="end_date" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>Month</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>Day</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>Year</label>
|
||||
<input
|
||||
id="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
|
||||
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="showValidation">
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
|
||||
<span class="icon icon--ok icon--green" aria-hidden="true"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path></svg></span>
|
||||
|
||||
</div>
|
||||
<div class="usa-form-group-date-ok" v-else>
|
||||
|
||||
<span class="icon icon--alert icon--red" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#fdb81e">
|
||||
<path d="M8 16c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zM8 2C4.691 2 2 4.691 2 8s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 8c-.552 0-1-.447-1-1V4c0-.552.448-1 1-1s1 .448 1 1v5c0 .553-.448 1-1 1zm0 3c-.26 0-.52-.11-.71-.29-.18-.19-.29-.45-.29-.71 0-.271.11-.521.29-.71.38-.37 1.05-.37 1.42 0 .18.189.29.45.29.71s-.11.52-.29.71c-.19.18-.45.29-.71.29z"/>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="usa-input-error-message form-has-errors">
|
||||
<p v-for="error in popErrors" :key="error" v-html='error'></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="$root.activeModal === removeModalId" v-cloak>
|
||||
<div :id='"modal--" + removeModalId' class='modal modal--dismissable'>
|
||||
<div class='modal__container'>
|
||||
<div class='modal__dialog' role='dialog' aria-modal='true'>
|
||||
<div class='modal__body'>
|
||||
<div class="task-order__modal-cancel">
|
||||
<h1 v-html='"Do you want to remove " + clinTitle + "?"'></h1>
|
||||
<div class="task-order__modal-cancel_buttons">
|
||||
<button
|
||||
v-on:click='closeModal(removeModalId)'
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
No, go back
|
||||
</button>
|
||||
<button
|
||||
v-on:click="removeClin()"
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
Yes, remove CLIN
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type='button' class='icon-link modal__dismiss' v-on:click='closeModal(removeModalId)'>
|
||||
|
||||
<span class="icon icon--x " aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M2 2l12 12M14 15c-.256 0-.512-.098-.707-.293l-12-12c-.391-.391-.391-1.023 0-1.414s1.023-.391 1.414 0l12 12c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293zm0-13L2 14"/><path d="M2 15c-.256 0-.512-.098-.707-.293-.391-.391-.391-1.023 0-1.414l12-12c.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414l-12 12C2.512 14.902 2.256 15 2 15z"/></svg>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
Close
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</clin-fields>
|
319
templates/components/clin_fields.html
Normal file
319
templates/components/clin_fields.html
Normal file
@ -0,0 +1,319 @@
|
||||
{% from "components/clin_dollar_amount.html" import CLINDollarAmount %}
|
||||
{% from 'components/alert.html' import Alert %}
|
||||
{% from 'components/date_picker.html' import DatePicker %}
|
||||
{% from 'components/icon.html' import Icon %}
|
||||
{% from 'components/options_input.html' import OptionsInput %}
|
||||
{% from 'components/text_input.html' import TextInput %}
|
||||
|
||||
{% macro CLINFields(contract_start, contract_end, fields=None, index=None) %}
|
||||
<clin-fields
|
||||
{% if fields %}
|
||||
v-bind:initial-clin-index='{{ index }}'
|
||||
v-bind:initial-total='{{ fields.total_amount.data or 0 }}'
|
||||
v-bind:initial-obligated='{{ fields.obligated_amount.data or 0 }}'
|
||||
v-bind:initial-start-date="'{{ fields.start_date.data | string }}'"
|
||||
v-bind:initial-end-date="'{{ fields.end_date.data | string }}'"
|
||||
v-bind:initial-clin-number="'{{ fields.number.data | string }}'"
|
||||
{% else %}
|
||||
v-bind:initial-clin-index='clinIndex'
|
||||
v-bind:initial-clin-type="'JEDI_CLIN_1'"
|
||||
{% endif %}
|
||||
v-bind:contract-start="'{{ contract_start | string }}'"
|
||||
v-bind:contract-end="'{{ contract_end | string }}'"
|
||||
inline-template>
|
||||
<div class="clin-card" v-if="showClin">
|
||||
<div class="card__title">
|
||||
<span class="h4" v-html='clinTitle'></span>
|
||||
<button
|
||||
v-if='clinIndex > 0'
|
||||
class="icon-link icon-link__remove-clin"
|
||||
v-on:click="openModal(removeModalId)"
|
||||
type="button">
|
||||
{{ Icon(name='x') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.clin_details' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% if fields %}
|
||||
{{ TextInput(fields.number, watch=True, optional=False) }}
|
||||
{% else %}
|
||||
<textinput :name="'clins-' + clinIndex + '-number'" :watch='true'
|
||||
inline-template>
|
||||
<div v-bind:class="['usa-input usa-input--validation--' + validation, { 'usa-input--error': showError, 'usa-input--success': showValid, 'usa-input--validation--paragraph': paragraph, 'no-max-width': noMaxWidth }]">
|
||||
<label :for="name">
|
||||
<span v-show='showError'>{{ Icon('alert',classes="icon-validation") }}</span>
|
||||
<span v-show='showValid'>{{ Icon('ok',classes="icon-validation") }}</span>
|
||||
<div class="usa-input__title">{{ 'task_orders.form.clin_number_label' | translate }}</div>
|
||||
</label>
|
||||
|
||||
<masked-input
|
||||
v-on:input='onInput'
|
||||
v-on:blur='onBlur'
|
||||
v-on:change='onChange'
|
||||
v-bind:value='value'
|
||||
v-bind:mask='mask'
|
||||
v-bind:pipe='pipe'
|
||||
v-bind:keep-char-positions='keepCharPositions'
|
||||
v-bind:aria-invalid='showError'
|
||||
type='text'
|
||||
:id='name'
|
||||
ref='input'>
|
||||
</masked-input>
|
||||
|
||||
<input type='hidden' v-bind:value='rawValue' :name='name' />
|
||||
|
||||
<template v-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class='usa-input__message'></span>
|
||||
</template>
|
||||
</div>
|
||||
</textinput>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% if fields %}
|
||||
{{ OptionsInput(fields.jedi_clin_type, watch=True, show_validation=False, optional=False) }}
|
||||
{% else %}
|
||||
<optionsinput :name="'clins-' + clinIndex + '-jedi_clin_type'" :watch='true' :optional='false' inline-template>
|
||||
<div v-bind:class="['usa-input', { 'usa-input--error': showError, 'usa-input--success': showValid }]">
|
||||
<fieldset data-ally-disabled="true" class="usa-input__choices" v-on:change="onInput">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.clin_type_label' | translate }}
|
||||
</div>
|
||||
</legend>
|
||||
<select :id='name' :name='name'>
|
||||
<option value="JEDI_CLIN_1">{{ "forms.task_order.clin_01_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_2">{{ "forms.task_order.clin_02_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_3">{{ "forms.task_order.clin_03_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_4">{{ "forms.task_order.clin_04_label" | translate }}</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
</div>
|
||||
</optionsinput>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.clin_funding' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if fields %}
|
||||
{{ CLINDollarAmount("total", field=fields.total_amount) }}
|
||||
{{ CLINDollarAmount("obligated", field=fields.obligated_amount, funding_validation=True) }}
|
||||
{% else %}
|
||||
{{ CLINDollarAmount("total") }}
|
||||
{{ CLINDollarAmount("obligated", funding_validation=True) }}
|
||||
{% endif %}
|
||||
|
||||
<div class="h5 clin-card__title">Percent Obligated</div>
|
||||
<p id="percent-obligated" v-html='percentObligated'></p>
|
||||
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.pop' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
{% set contract_end_formatted = contract_end | dateFromString(formatter="%Y-%m-%d") | formattedDate(formatter="%B %d, %Y") %}
|
||||
{% if fields %}
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{{ DatePicker(fields.start_date, watch=True, optional=False) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% call DatePicker(fields.end_date, watch=True, optional=False) %}
|
||||
{{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': contract_end_formatted})) }}
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector :name-tag="'clins-' + clinIndex + '-start_date'" :watch='true' :optional='false' inline-template>
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.pop_start' | translate }}
|
||||
</div>
|
||||
<p class='usa-input__help'>
|
||||
{{ 'task_orders.form.pop_example' | translate }}
|
||||
</p>
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input :name="name" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>{{ 'components.date_selector.month' | translate }}</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>{{ 'components.date_selector.day' | translate }}</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>{{ 'components.date_selector.year' | translate }}</label>
|
||||
<input
|
||||
name="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
{{ Icon("ok", classes="icon--green") }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector :name-tag="'clins-' + clinIndex + '-end_date'" :watch='true' :optional='false' inline-template>
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.pop_end' | translate }}
|
||||
</div>
|
||||
|
||||
{{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': contract_end_formatted})) }}
|
||||
|
||||
<p class='usa-input__help'>
|
||||
{{ 'task_orders.form.pop_example' | translate }}
|
||||
</p>
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input :name="name" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>{{ 'components.date_selector.month' | translate }}</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>{{ 'components.date_selector.day' | translate }}</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>{{ 'components.date_selector.year' | translate }}</label>
|
||||
<input
|
||||
name="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
{{ Icon("ok", classes="icon--green") }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-row">
|
||||
<div class="usa-input-error-message form-has-errors">
|
||||
<p v-for="error in popErrors" :key="error" v-html='error'></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="$root.activeModal === removeModalId" v-cloak>
|
||||
<div :id='"modal--" + removeModalId' class='modal modal--dismissable'>
|
||||
<div class='modal__container'>
|
||||
<div class='modal__dialog' role='dialog' aria-modal='true'>
|
||||
<div class='modal__body'>
|
||||
<div class="task-order__modal-cancel">
|
||||
<h1 v-html='"{{ 'task_orders.form.clin_remove_text' | translate }}" + clinTitle + "?"'></h1>
|
||||
<div class="task-order__modal-cancel_buttons">
|
||||
<button
|
||||
v-on:click='closeModal(removeModalId)'
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
{{ 'task_orders.form.clin_remove_cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
v-on:click="removeClin()"
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
{{ 'task_orders.form.clin_remove_confirm' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type='button' class='icon-link modal__dismiss' v-on:click='closeModal(removeModalId)'>
|
||||
{{ Icon('x') }}
|
||||
<span>
|
||||
{{ "common.close" | translate }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</clin-fields>
|
||||
{% endmacro %}
|
@ -1,11 +1,7 @@
|
||||
{% extends "task_orders/builder_base.html" %}
|
||||
|
||||
{% from 'components/alert.html' import Alert %}
|
||||
{% from 'components/date_picker.html' import DatePicker %}
|
||||
{% from 'components/icon.html' import Icon %}
|
||||
{% from 'components/options_input.html' import OptionsInput %}
|
||||
{% from 'components/text_input.html' import TextInput %}
|
||||
{% from "components/clin_dollar_amount.html" import CLINDollarAmount %}
|
||||
{% from "components/clin_fields.html" import CLINFields %}
|
||||
{% from 'task_orders/form_header.html' import TOFormStepHeader %}
|
||||
|
||||
{% set action = url_for("task_orders.submit_form_step_three_add_clins", task_order_id=task_order_id) %}
|
||||
@ -13,330 +9,17 @@
|
||||
{% set previous_button_link = url_for("task_orders.form_step_two_add_number", task_order_id=task_order_id) %}
|
||||
{% set step = "3" %}
|
||||
|
||||
{% macro CLINFields(fields=None, index=None) %}
|
||||
<clin-fields
|
||||
{% if fields %}
|
||||
v-bind:initial-clin-index='{{ index }}'
|
||||
v-bind:initial-total='{{ fields.total_amount.data or 0 }}'
|
||||
v-bind:initial-obligated='{{ fields.obligated_amount.data or 0 }}'
|
||||
v-bind:initial-start-date="'{{ fields.start_date.data | string }}'"
|
||||
v-bind:initial-end-date="'{{ fields.end_date.data | string }}'"
|
||||
v-bind:initial-clin-number="'{{ fields.number.data | string }}'"
|
||||
{% else %}
|
||||
v-bind:initial-clin-index='clinIndex'
|
||||
v-bind:initial-clin-type="'JEDI_CLIN_1'"
|
||||
{% endif %}
|
||||
v-bind:contract-start="'{{ contract_start | string }}'"
|
||||
v-bind:contract-end="'{{ contract_end | string }}'"
|
||||
inline-template>
|
||||
<div class="clin-card" v-if="showClin">
|
||||
<div class="card__title">
|
||||
<span class="h4" v-html='clinTitle'></span>
|
||||
<button
|
||||
v-if='$parent.clinIndex > 0'
|
||||
class="icon-link icon-link__remove-clin"
|
||||
v-on:click="openModal(removeModalId)"
|
||||
type="button">
|
||||
{{ Icon(name='x') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.clin_details' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% if fields %}
|
||||
{{ TextInput(fields.number, watch=True, optional=False) }}
|
||||
{% else %}
|
||||
<textinput :name="'clins-' + clinIndex + '-number'" :watch='true'
|
||||
inline-template>
|
||||
<div v-bind:class="['usa-input usa-input--validation--' + validation, { 'usa-input--error': showError, 'usa-input--success': showValid, 'usa-input--validation--paragraph': paragraph, 'no-max-width': noMaxWidth }]">
|
||||
<label :for="name">
|
||||
<span v-show='showError'>{{ Icon('alert',classes="icon-validation") }}</span>
|
||||
<span v-show='showValid'>{{ Icon('ok',classes="icon-validation") }}</span>
|
||||
<div class="usa-input__title">{{ 'task_orders.form.clin_number_label' | translate }}</div>
|
||||
</label>
|
||||
|
||||
<masked-input
|
||||
v-on:input='onInput'
|
||||
v-on:blur='onBlur'
|
||||
v-on:change='onChange'
|
||||
v-bind:value='value'
|
||||
v-bind:mask='mask'
|
||||
v-bind:pipe='pipe'
|
||||
v-bind:keep-char-positions='keepCharPositions'
|
||||
v-bind:aria-invalid='showError'
|
||||
type='text'
|
||||
:id='name'
|
||||
ref='input'>
|
||||
</masked-input>
|
||||
|
||||
<input type='hidden' v-bind:value='rawValue' :name='name' />
|
||||
|
||||
<template v-if='showError'>
|
||||
<span class='usa-input__message' v-html='validationError'></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class='usa-input__message'></span>
|
||||
</template>
|
||||
</div>
|
||||
</textinput>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% if fields %}
|
||||
{{ OptionsInput(fields.jedi_clin_type, watch=True, show_validation=False, optional=False) }}
|
||||
{% else %}
|
||||
<optionsinput :name="'clins-' + clinIndex + '-jedi_clin_type'" :watch='true' :optional='false' inline-template>
|
||||
<div v-bind:class="['usa-input', { 'usa-input--error': showError, 'usa-input--success': showValid }]">
|
||||
<fieldset data-ally-disabled="true" class="usa-input__choices" v-on:change="onInput">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.clin_type_label' | translate }}
|
||||
</div>
|
||||
</legend>
|
||||
<select :id='name' :name='name'>
|
||||
<option value="JEDI_CLIN_1">{{ "forms.task_order.clin_01_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_2">{{ "forms.task_order.clin_02_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_3">{{ "forms.task_order.clin_03_label" | translate }}</option>
|
||||
<option value="JEDI_CLIN_4">{{ "forms.task_order.clin_04_label" | translate }}</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
</div>
|
||||
</optionsinput>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.clin_funding' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if fields %}
|
||||
{{ CLINDollarAmount("total", field=fields.total_amount) }}
|
||||
{{ CLINDollarAmount("obligated", field=fields.obligated_amount, funding_validation=True) }}
|
||||
{% else %}
|
||||
{{ CLINDollarAmount("total") }}
|
||||
{{ CLINDollarAmount("obligated", funding_validation=True) }}
|
||||
{% endif %}
|
||||
|
||||
<div class="h5 clin-card__title">Percent Obligated</div>
|
||||
<p v-html='percentObligated'></p>
|
||||
|
||||
<hr>
|
||||
<div class="form-row">
|
||||
<div class="h4 clin-card__title">
|
||||
{{ 'task_orders.form.pop' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
{% set contract_end_formatted = contract_end | dateFromString(formatter="%Y-%m-%d") | formattedDate(formatter="%B %d, %Y") %}
|
||||
{% if fields %}
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{{ DatePicker(fields.start_date, watch=True, optional=False) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
{% call DatePicker(fields.end_date, watch=True, optional=False) %}
|
||||
{{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': contract_end_formatted})) }}
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector :name-tag="'clins-' + clinIndex + '-start_date'" :watch='true' :optional='false' inline-template>
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.pop_start' | translate }}
|
||||
</div>
|
||||
<p class='usa-input__help'>
|
||||
{{ 'task_orders.form.pop_example' | translate }}
|
||||
</p>
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input :name="name" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>{{ 'components.date_selector.month' | translate }}</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>{{ 'components.date_selector.day' | translate }}</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>{{ 'components.date_selector.year' | translate }}</label>
|
||||
<input
|
||||
name="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
{{ Icon("ok", classes="icon--green") }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<date-selector :name-tag="'clins-' + clinIndex + '-end_date'" :watch='true' :optional='false' inline-template>
|
||||
<fieldset class="usa-input date-picker" v-bind:class="{ 'usa-input--success': isDateValid && showValidation }">
|
||||
<legend>
|
||||
<div class="usa-input__title">
|
||||
{{ 'task_orders.form.pop_end' | translate }}
|
||||
</div>
|
||||
|
||||
{{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': contract_end_formatted})) }}
|
||||
|
||||
<p class='usa-input__help'>
|
||||
{{ 'task_orders.form.pop_example' | translate }}
|
||||
</p>
|
||||
</legend>
|
||||
|
||||
<div class="date-picker-component">
|
||||
<input :name="name" v-bind:value="formattedDate" v-on:change="onInput" type="hidden" />
|
||||
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label>{{ 'components.date_selector.month' | translate }}</label>
|
||||
<input
|
||||
name="date-month"
|
||||
max="12"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (month && !isMonthValid) }"
|
||||
v-model="month"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label>{{ 'components.date_selector.day' | translate }}</label>
|
||||
<input
|
||||
name="date-day"
|
||||
maxlength="2"
|
||||
min="1"
|
||||
type="number"
|
||||
v-bind:class="{ 'usa-input-error': (day && !isDayValid) }"
|
||||
v-bind:max="daysMaxCalculation"
|
||||
v-model="day"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label>{{ 'components.date_selector.year' | translate }}</label>
|
||||
<input
|
||||
name="date-year"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
v-model="year"
|
||||
v-on:change="onInput"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="usa-form-group-date-ok" v-if="isDateValid">
|
||||
{{ Icon("ok", classes="icon--green") }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</date-selector>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-row">
|
||||
<div class="usa-input-error-message form-has-errors">
|
||||
<p v-for="error in popErrors" :key="error" v-html='error'></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="$root.activeModal === removeModalId" v-cloak>
|
||||
<div :id='"modal--" + removeModalId' class='modal modal--dismissable'>
|
||||
<div class='modal__container'>
|
||||
<div class='modal__dialog' role='dialog' aria-modal='true'>
|
||||
<div class='modal__body'>
|
||||
<div class="task-order__modal-cancel">
|
||||
<h1 v-html='"{{ 'task_orders.form.clin_remove_text' | translate }}" + clinTitle + "?"'></h1>
|
||||
<div class="task-order__modal-cancel_buttons">
|
||||
<button
|
||||
v-on:click='closeModal(removeModalId)'
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
{{ 'task_orders.form.clin_remove_cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
v-on:click="removeClin()"
|
||||
class="usa-button usa-button-primary"
|
||||
type="button">
|
||||
{{ 'task_orders.form.clin_remove_confirm' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type='button' class='icon-link modal__dismiss' v-on:click='closeModal(removeModalId)'>
|
||||
{{ Icon('x') }}
|
||||
<span>
|
||||
{{ "common.close" | translate }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</clin-fields>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% block to_builder_form_field %}
|
||||
<div>
|
||||
{{ TOFormStepHeader('task_orders.form.clin_title' | translate, 'task_orders.form.clin_description' | translate, task_order.number) }}
|
||||
|
||||
{% for clin in form.clins %}
|
||||
{{ CLINFields(clin, index=loop.index - 1) }}
|
||||
{{ CLINFields(contract_start, contract_end, clin, index=loop.index - 1) }}
|
||||
{% endfor %}
|
||||
|
||||
<div v-for="clin in clins">
|
||||
{{ CLINFields() }}
|
||||
{{ CLINFields(contract_start, contract_end) }}
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
@ -1,11 +1,12 @@
|
||||
import pytest
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from wtforms.widgets import CheckboxInput
|
||||
from wtforms import Form, FormField
|
||||
from wtforms.fields import StringField
|
||||
from wtforms.validators import InputRequired
|
||||
from wtforms import Form, FormField
|
||||
from wtforms.widgets import CheckboxInput
|
||||
|
||||
from atst.forms.task_order import CLINForm
|
||||
from atst.forms.task_order import TaskOrderForm
|
||||
from atst.models import Permissions
|
||||
from atst.routes.task_orders.new import render_task_orders_edit
|
||||
@ -92,7 +93,7 @@ def test_make_upload_input_error_template(upload_input_macro, task_order_form):
|
||||
write_template(rendered_upload_macro, "upload_input_error_template.html")
|
||||
|
||||
|
||||
def test_make_task_order_step3_template(app, request_ctx):
|
||||
def test_make_task_order_with_clin_form_template(app, request_ctx):
|
||||
request_ctx.g.current_user = factories.UserFactory.create()
|
||||
request_ctx.g.application = None
|
||||
request_ctx.g.portfolio = None
|
||||
@ -122,3 +123,15 @@ def test_make_task_order_step3_template(app, request_ctx):
|
||||
dom = BeautifulSoup(step3, "html.parser")
|
||||
to_form = dom.find("to-form")
|
||||
write_template(str(to_form), "to_form.html")
|
||||
|
||||
|
||||
def test_make_clin_fields(env, app):
|
||||
step3_template = env.get_template("components/clin_fields.html")
|
||||
clin_fields_macro = getattr(step3_template.module, "CLINFields")
|
||||
clin_fields = clin_fields_macro(
|
||||
app.config.get("CONTRACT_START_DATE"),
|
||||
app.config.get("CONTRACT_END_DATE"),
|
||||
CLINForm(),
|
||||
0,
|
||||
)
|
||||
write_template(clin_fields, "clin_fields.html")
|
||||
|
Loading…
x
Reference in New Issue
Block a user