Skip to content
Snippets Groups Projects
Commit 634e65c1 authored by Sébastien DA ROCHA's avatar Sébastien DA ROCHA :bicyclist:
Browse files

Merge branch 'redmine-issue/14427' into 'develop'

REDMINE_ISSUE-14427 | Listes de valeurs pré-enregistrées et auto-complétion à la saisie d'un signalement

See merge request geocontrib/geocontrib-frontend!479
parents 5aefb671 e8dbc915
No related branches found
No related tags found
1 merge request!479REDMINE_ISSUE-14427 | Listes de valeurs pré-enregistrées et auto-complétion à la saisie d'un signalement
...@@ -50,6 +50,67 @@ ...@@ -50,6 +50,67 @@
</li> </li>
</ul> </ul>
</div> </div>
<div
v-else-if="field && field.field_type === 'pre_recorded_list'"
>
<label
v-if="displayLabels"
:for="field.name"
:class="{ required: field.is_mandatory }"
>
{{ field.label }}
</label>
<Multiselect
v-model="selectedPrerecordedValue"
:options="selectedPrerecordedListValues"
:options-limit="10"
:allow-empty="!field.is_mandatory"
track-by="label"
label="label"
:reset-after="false"
select-label=""
selected-label=""
deselect-label=""
:searchable="true"
:placeholder="'Recherchez une valeur de la liste pré-définie ...'"
:show-no-results="true"
:loading="loadingPrerecordedListValues"
:clear-on-select="false"
:preserve-search="false"
@search-change="search"
@select="selectPrerecordedValue"
>
<template slot="clear">
<div
v-if="selectedPrerecordedValue"
class="multiselect__clear"
@click.prevent.stop="clear"
>
<i
class="close icon"
aria-hidden="true"
/>
</div>
</template>
<span slot="noResult">
Aucun résultat.
</span>
<span slot="noOptions">
Saisissez les premiers caractères ...
</span>
</Multiselect>
<ul
v-if="field.is_mandatory && error"
:id="`errorlist-extra-form-${field.name}`"
class="errorlist"
>
<li>
{{ error }}
</li>
</ul>
</div>
<div v-else-if="field && field.field_type === 'integer'"> <div v-else-if="field && field.field_type === 'integer'">
<label <label
v-if="displayLabels" v-if="displayLabels"
...@@ -177,12 +238,16 @@ ...@@ -177,12 +238,16 @@
<script> <script>
import Dropdown from '@/components/Dropdown.vue'; import Dropdown from '@/components/Dropdown.vue';
import Multiselect from 'vue-multiselect';
import { mapState, mapMutations, mapActions } from 'vuex';
export default { export default {
name: 'FeatureExtraForm', name: 'FeatureExtraForm',
components: { components: {
Dropdown, Dropdown,
Multiselect
}, },
props: { props: {
...@@ -194,11 +259,18 @@ export default { ...@@ -194,11 +259,18 @@ export default {
data() { data() {
return { return {
error: null error: null,
prerecordedListSearchQuery: null,
loadingPrerecordedListValues: false,
selectedPrerecordedValue: null
}; };
}, },
computed: { computed: {
...mapState('feature-type', [
'selectedPrerecordedListValues'
]),
selected_extra_form_list: { selected_extra_form_list: {
get() { get() {
return this.field.value || ''; return this.field.value || '';
...@@ -221,10 +293,41 @@ export default { ...@@ -221,10 +293,41 @@ export default {
if (newValue) { if (newValue) {
this.error = null; this.error = null;
} }
},
prerecordedListSearchQuery(newValue) {
if (newValue) {
this.loadingPrerecordedListValues = true;
this.GET_SELECTED_PRERECORDED_LIST_VALUES({
name: this.field.options[0],
pattern: newValue
})
.then(() => {
this.loadingPrerecordedListValues = false;
})
.catch(() => {
this.loadingPrerecordedListValues = false;
});
} else {
this.SET_SELECTED_PRERECORDED_LIST_VALUES([]);
}
}
},
created() {
console.log(this.field.value);
if (this.field.value) {
this.selectedPrerecordedValue = { label: this.field.value };
} }
}, },
methods: { methods: {
...mapMutations('feature-type', [
'SET_SELECTED_PRERECORDED_LIST_VALUES'
]),
...mapActions('feature-type', [
'GET_SELECTED_PRERECORDED_LIST_VALUES'
]),
updateStore_extra_form(evt) { updateStore_extra_form(evt) {
const newExtraForm = this.field; const newExtraForm = this.field;
if (this.field.field_type === 'boolean') { if (this.field.field_type === 'boolean') {
...@@ -244,6 +347,21 @@ export default { ...@@ -244,6 +347,21 @@ export default {
this.error = null; this.error = null;
} }
return isValid; return isValid;
},
search(text) {
this.prerecordedListSearchQuery = text;
},
selectPrerecordedValue(e) {
this.selectedPrerecordedValue = e.label;
this.prerecordedListSearchQuery = null;
this.updateStore_extra_form({ target: { value: this.selectedPrerecordedValue } });
},
clear() {
this.selectedPrerecordedValue = null;
this.prerecordedListSearchQuery = null;
} }
}, },
}; };
......
...@@ -167,13 +167,38 @@ ...@@ -167,13 +167,38 @@
</li> </li>
</ul> </ul>
</div> </div>
<div
v-if="selectedFieldType === 'Liste de valeurs pré-enregistrées'"
class="field required"
>
<label>{{
form.options.label
}}</label>
<Dropdown
:options="preRecordedLists"
:selected="arrayOption"
:selection.sync="arrayOption"
/>
<ul
id="errorlist"
class="errorlist"
>
<li
v-for="error in form.options.errors"
:key="error"
>
{{ error }}
</li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex'; import { mapState, mapActions } from 'vuex';
import Dropdown from '@/components/Dropdown.vue'; import Dropdown from '@/components/Dropdown.vue';
...@@ -202,6 +227,7 @@ export default { ...@@ -202,6 +227,7 @@ export default {
{ name: 'Chaîne de caractères', value: 'char' }, { name: 'Chaîne de caractères', value: 'char' },
{ name: 'Date', value: 'date' }, { name: 'Date', value: 'date' },
{ name: 'Liste de valeurs', value: 'list' }, { name: 'Liste de valeurs', value: 'list' },
{ name: 'Liste de valeurs pré-enregistrées', value: 'pre_recorded_list' },
{ name: 'Nombre entier', value: 'integer' }, { name: 'Nombre entier', value: 'integer' },
{ name: 'Nombre décimal', value: 'decimal' }, { name: 'Nombre décimal', value: 'decimal' },
{ name: 'Texte multiligne', value: 'text' }, { name: 'Texte multiligne', value: 'text' },
...@@ -268,12 +294,14 @@ export default { ...@@ -268,12 +294,14 @@ export default {
value: [], value: [],
}, },
}, },
selectedPrerecordedList: null
}; };
}, },
computed: { computed: {
...mapState('feature-type', [ ...mapState('feature-type', [
'customForms' 'customForms',
'preRecordedLists'
]), ]),
selectedFieldType: { selectedFieldType: {
// getter // getter
...@@ -288,6 +316,9 @@ export default { ...@@ -288,6 +316,9 @@ export default {
}, },
// setter // setter
set(newValue) { set(newValue) {
if (newValue.value === 'pre_recorded_list') {
this.GET_PRERECORDED_LISTS();
}
this.form.field_type.value = newValue.value; this.form.field_type.value = newValue.value;
this.form = { ...this.form }; // ! quick & dirty fix for getter not updating because of Vue caveat https://vuejs.org/v2/guide/reactivity.html#For-Objects this.form = { ...this.form }; // ! quick & dirty fix for getter not updating because of Vue caveat https://vuejs.org/v2/guide/reactivity.html#For-Objects
// Vue.set(this.form.field_type, "value", newValue.value); // ? vue.set didn't work, maybe should flatten form ? // Vue.set(this.form.field_type, "value", newValue.value); // ? vue.set didn't work, maybe should flatten form ?
...@@ -314,6 +345,9 @@ export default { ...@@ -314,6 +345,9 @@ export default {
}, },
methods: { methods: {
...mapActions('feature-type', [
'GET_PRERECORDED_LISTS'
]),
setIsFieldMandatory(e) { setIsFieldMandatory(e) {
this.form.isFieldMandatory = e.target.checked; this.form.isFieldMandatory = e.target.checked;
...@@ -389,8 +423,13 @@ export default { ...@@ -389,8 +423,13 @@ export default {
}, },
checkListOptions() { checkListOptions() {
if (this.form.field_type.value !== 'list') return true; if (!['list', 'pre_recorded_list'].includes(this.form.field_type.value)) return true;
return this.form.options.value.length >= 2 && !this.form.options.value.includes(''); if (this.form.field_type.value === 'list') {
return this.form.options.value.length >= 2 && !this.form.options.value.includes('');
}
if (this.form.field_type.value === 'pre_recorded_list') {
return this.form.options.value.length === 1;
}
}, },
checkCustomForm() { checkCustomForm() {
......
import axios from '@/axios-client.js'; import axios from '@/axios-client.js';
import store from '../store'; import store from '@/store';
const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE; const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
......
...@@ -30,6 +30,8 @@ const feature_type = { ...@@ -30,6 +30,8 @@ const feature_type = {
feature_types: [], feature_types: [],
fileToImport: null, fileToImport: null,
importFeatureTypeData: [], importFeatureTypeData: [],
preRecordedLists: [],
selectedPrerecordedListValues: []
}, },
getters: { getters: {
...@@ -83,6 +85,12 @@ const feature_type = { ...@@ -83,6 +85,12 @@ const feature_type = {
SET_FILE_TO_IMPORT(state, payload) { SET_FILE_TO_IMPORT(state, payload) {
state.fileToImport = payload; state.fileToImport = payload;
}, },
SET_PRERECORDED_LISTS(state, payload) {
state.preRecordedLists = payload;
},
SET_SELECTED_PRERECORDED_LIST_VALUES(state, payload) {
state.selectedPrerecordedListValues = payload.slice(0, 10).map(el => { return { label: el };});
}
}, },
actions: { actions: {
...@@ -100,6 +108,32 @@ const feature_type = { ...@@ -100,6 +108,32 @@ const feature_type = {
}); });
}, },
async GET_PRERECORDED_LISTS({ commit }) {
try {
const response = await axios.get(
`${this.state.configuration.VUE_APP_DJANGO_API_BASE}prerecorded-list-values/`
);
if (response.status === 200) {
commit('SET_PRERECORDED_LISTS', response.data.map(el => el.name));
}
} catch (err) {
console.error(err);
}
},
async GET_SELECTED_PRERECORDED_LIST_VALUES({ commit }, { name, pattern }) {
try {
const response = await axios.get(
`${this.state.configuration.VUE_APP_DJANGO_API_BASE}prerecorded-list-values/${name}/?pattern=${pattern}`
);
if (response.status === 200) {
commit('SET_SELECTED_PRERECORDED_LIST_VALUES', response.data);
}
} catch (err) {
console.error(err);
}
},
async SEND_FEATURE_TYPE({ state, getters, rootState }, requestType) { async SEND_FEATURE_TYPE({ state, getters, rootState }, requestType) {
const data = { const data = {
title: state.form.title.value, title: state.form.title.value,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment