Commit 60e425f4 authored by Tobinsk's avatar Tobinsk
Browse files

Merge branch '21-validate-matching-form' into 'master'

Resolve "Validate matching form"

Closes #21

See merge request !26
parents eb14d151 a177e789
Pipeline #6480 passed with stage
in 4 minutes and 41 seconds
......@@ -11,9 +11,9 @@
<b-row v-if="isNew">
<div class="col-sm-3 offset-sm-9 d-flex justify-content-end">
<b-button-group>
<b-button @click="addField">Add field</b-button>
<b-button @click="preSave">Run</b-button>
<b-button @click="preTest">Test</b-button>
<b-button @click="addField"><b-icon icon="plus"></b-icon> Option</b-button>
<b-button @click="preTest"><b-icon icon="calculator"></b-icon> Test</b-button>
<b-button @click="preSave"><b-icon icon="play"></b-icon> Match</b-button>
</b-button-group>
</div>
</b-row>
......@@ -27,13 +27,16 @@
id="group-name"
label="Name for the matching"
label-for="name">
<b-input name="name" id="name" v-model="single.name" :disabled="!isNew" required="required"></b-input>
<b-input name="name" id="name" v-model="$v.single.name.$model" :disabled="!isNew" required="required" :state="validateState('name')"
></b-input>
<b-form-invalid-feedback id="name">The name is a required field.</b-form-invalid-feedback>
</b-form-group>
</b-col>
</b-row>
<b-row v-for="(field, index) in single.parameters" :key="index">
<div class="col-11">
<MatchField v-bind:value.sync="single.parameters[index]" :disabled="!isNew"/>
<MatchField v-bind:value.sync="single.parameters[index]" :disabled="!isNew" :id="`parameter-${index}`" @update:value="validateParameter(index)"/>
<div class="invalid-feedback-1" v-show="!$v.single.parameters.$each.$iter[index].field.required">Please select a field.</div>
</div>
<div class="col-1 d-flex align-items-center justify-content-end" v-if="isNew">
<b-button @click="removeField(index)">
......@@ -41,6 +44,11 @@
</b-button>
</div>
</b-row>
<b-row v-show="!$v.single.parameters.required" class="invalid-feedback-1">
<div class="col-12">
You need to configure at least one matching option.
</div>
</b-row>
</b-form>
</FormContainer>
</transition>
......@@ -52,6 +60,7 @@
import MatchField from "@/components/MatchField";
import FormContainer from "@/components/FormContainer";
import {mapActions, mapGetters, mapMutations} from 'vuex';
import { required, minLength, between } from 'vuelidate/lib/validators'
export default {
name: "MatchForm",
components: {MatchField, FormContainer},
......@@ -65,6 +74,23 @@
loading: false,
}
},
validations: {
single: {
name: {
required,
minLength: minLength(4),
},
parameters: {
required,
minLength: minLength(1),
$each: {
field: {
required,
}
}
}
}
},
mounted() {
// check if new
if (this.$route.params.id !== 'new') {
......@@ -81,14 +107,22 @@
...mapActions('match', {'new': 'new', 'singleAction': 'single'}),
...mapActions('proposal', ['test']),
/**
* Save
* Pre-save hook. At the end we call save
**/
async preSave() {
// Validate form
this.$v.form.$touch();
if (this.$v.form.$anyError) {
return;
}
// set loading flag and send to server
this.loading = true;
await this.new({
name: this.single.name,
parameters: this.single.parameters,
});
// go back to overview
// wait until ES sync
setTimeout(() => {
......@@ -101,9 +135,12 @@
* Don't use a pagination. This is just to check if we find something
*/
async preTest() {
if(this.single.name === '') {
return
// Validate form
this.$v.single.$touch();
if (this.$v.single.$anyError) {
return;
}
await this.test(
{
name: this.single.name,
......@@ -111,6 +148,19 @@
}
)
},
/**
* Validate a field
* @param name {string}
*/
validateState(name) {
const { $dirty, $error } = this.$v.single[name];
return $dirty ? !$error : null;
},
validateParameter(index) {
const { $dirty, $error } = this.$v.single.parameters.$each.$iter[index];
return $dirty ? !$error : null;
},
/**
* Remove single search field
* @param index
......@@ -118,6 +168,7 @@
removeField(index) {
this.single.parameters.splice(index,1);
},
/**
* Add single search field
*/
......@@ -129,7 +180,8 @@
option2: '',
type: 'string',
});
}
this.$v.single.parameters.$each.$iter[this.single.parameters.length - 1].$touch()
},
}
}
</script>
......@@ -155,4 +207,12 @@
overflow: hidden;
backface-visibility: hidden;
}
.invalid-feedback-1 {
width: 100%;
margin-top: 0.25rem;
font-size: 80%;
color: #dc3545;
display: block
}
</style>
......@@ -7,7 +7,8 @@ import './plugins/bootstrap';
import VueKeycloakJs from '@dsb-norge/vue-keycloak-js';
import './plugins/fetch-interceptor';
import 'whatwg-fetch';
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
Vue.config.productionTip = false;
// in local dev we don't want to force a login. We will set the auth headers ourself in the fetch-interceptor
......
......@@ -24,7 +24,7 @@ import {
} from 'bootstrap-vue'
// load icons
import { BIcon, BIconSearch, BIconShuffle, BIconFilter, BIconPower, BIconBoxArrowUpRight, BIconPencil, BIconArrowBarUp,BIconTrash,BIconX, BIconCheck, BIconGear } from 'bootstrap-vue'
import { BIcon, BIconSearch, BIconShuffle, BIconFilter, BIconPower, BIconBoxArrowUpRight, BIconPencil, BIconArrowBarUp,BIconTrash,BIconX, BIconCheck, BIconGear, BIconPlus, BIconCalculator, BIconPlay } from 'bootstrap-vue'
// icons
vue.component('BIcon', BIcon)
vue.component('BIconSearch', BIconSearch)
......@@ -38,6 +38,9 @@ vue.component('BIconTrash', BIconTrash)
vue.component('BIconX', BIconX)
vue.component('BIconCheck', BIconCheck)
vue.component('BIconGear', BIconGear)
vue.component('BIconPlay', BIconPlay)
vue.component('BIconCalculator', BIconCalculator)
vue.component('BIconPlus', BIconPlus)
// components
vue.use(FormPlugin)
vue.use(FormGroupPlugin)
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment