Commit fda24ad8 authored by hypsug0's avatar hypsug0
Browse files

feat: WIP reactive sighting form

parent c4c7adb8
......@@ -931,3 +931,29 @@ BS Full screen Modal
.statBlock .statDesc {
font-size: 1em;
}
/* Vue Select */
.v-select {
height: 30px;
line-height: 30px;
padding: 0px;
min-width: 200px;
display: block;
width: 100%;
/* height: 36px; */
/* padding: 8px 12px; */
font-size: 13px;
line-height: 1.42857143;
color: #2c3e50;
background-color: #ffffff;
background-image: none;
border: 1px solid #dddddd;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
}
......@@ -1012,7 +1012,6 @@ const CountDetailObject = (lastdata) => {
gestation: null,
epiphyse: null,
chinspot: null,
etat_sexuel: null,
usure_dent: null,
comment: null,
}
......@@ -1040,6 +1039,106 @@ new Vue({
},
})
Vue.component('specieSelect', {
data() {
return {
selected: this.value,
dict: [],
options: [],
}
},
template: `<v-select class="form-control v-select-style" :options="options" :reduce="e => e.id" label="codesp" v-model="model">
<template v-slot:option="option">
<span class="label label-default" :class="option.sp_true?'label-success':'label-default' ">{{option.codesp}}</span> {{option.sci_name}}
</template>
<template #selected-option="{ sp_true, codesp, sci_name }">
<span class="label" :class="sp_true?'label-success':'label-default' ">{{codesp}}</span> {{sci_name}}
</template>
</v-select>`,
computed: {
model: {
get() {
console.debug('actual', this.selected)
return this.selected
},
set(newValue) {
console.debug('test', newValue)
this.$emit('input', newValue)
},
},
},
methods: {
getSpecieDict() {
if (localStorage.getItem('species') == null) {
console.debug('No dict in localStorage')
$http
.get('/api/v1/dict/specie')
.then((response) => {
console.debug(
'Saving downloaded dicts in localStorage',
response.data
)
this.options = response.data
localStorage.setItem(
'species',
JSON.stringify(this.options)
)
})
.catch((err) => {
console.error(err)
})
} else {
console.debug('loading species dict from localStorage')
this.options = JSON.parse(localStorage.getItem('species'))
}
this.options = this.options
.sort((a, b) => {
const ca = a.codesp,
cb = b.codesp
return ca < cb ? -1 : ca > cb ? 1 : 0
})
.sort((a, b) => Number(b.sp_true) - Number(a.sp_true))
},
},
mounted() {
this.getSpecieDict()
},
})
Vue.component('dictSelect', {
data() {
return {
selected: this.value,
}
},
props: {
options: {
type: Array,
required: true,
},
},
template: `<v-select class="form-control v-select-style" :options="options" :reduce="e => e.id" label="code" v-model="model">
<template v-slot:option="option">
<span class="label label-default">{{option.code}}</span> {{option.descr}}
</template>
<template #selected-option="{ code, descr }">
<span class="label label-default">{{code}}</span>&nbsp;{{descr}}
</template>
</v-select>`,
computed: {
model: {
get() {
console.debug('actual', this.selected)
return this.selected
},
set(newValue) {
console.debug('test', newValue)
this.$emit('input', newValue)
},
},
},
})
const sigthingFormApp = (id_session, type_contact) => {
VeeValidate.extend('positive', (value) => {
return value >= 0
......@@ -1088,9 +1187,15 @@ const sigthingFormApp = (id_session, type_contact) => {
selectedItem: 0,
typeContact: type_contact,
moreSightingForm: false,
dictSpecies: [],
errors: [],
}
},
methods: {
findCondition (dict, code) {
console.log('<findCondition>', dict.find(e => e.code === code))
return dict.find(e => e.code === code)
},
selectItem(i) {
this.selectedItem = i
},
......@@ -1168,6 +1273,7 @@ const sigthingFormApp = (id_session, type_contact) => {
})
.catch((err) => {
console.error(err)
this.errors.push(err.response.data)
})
},
deleteSighting(i) {
......@@ -1208,11 +1314,15 @@ const sigthingFormApp = (id_session, type_contact) => {
// this.data.forEach(e => this.postSighting(e))
},
filteredDict(dict, contact) {
return dict.filter((e) => e.contact == contact)
contact = contact || null
return contact ? dict.filter((e) => e.contact == contact) : dict
},
taxaSelectOptions(dict, contact) {
return
},
getDictSpecie() {
},
getDicts() {
if (localStorage.getItem('dicts') == null) {
console.debug('No dicts in localStorage')
......@@ -1223,9 +1333,10 @@ const sigthingFormApp = (id_session, type_contact) => {
'Saving downloaded dicts in localStorage',
response.data
)
this.dicts = response.data
localStorage.setItem(
'dicts',
JSON.stringify(response.data)
JSON.stringify(this.dicts)
)
})
.catch((err) => {
......@@ -1234,6 +1345,11 @@ const sigthingFormApp = (id_session, type_contact) => {
}
console.debug('loading dicts from localStorage')
this.dicts = JSON.parse(localStorage.getItem('dicts'))
this.dictSpecies = this.dicts.Specie.sort((a, b) => {
const ca = a.codesp,
cb = b.codesp
return ca < cb ? -1 : ca > cb ? 1 : 0
}).sort((a, b) => Number(b.sp_true) - Number(a.sp_true))
this.dictsLoaded = true
},
getAutocompleteData(obj) {
......@@ -1246,7 +1362,7 @@ const sigthingFormApp = (id_session, type_contact) => {
},
getData() {
$http
.get(sightingDataListUrl)
.get(this.url)
.then((response) => {
this.data = response.data?.results
if (this.data.length == 0) {
......@@ -1271,6 +1387,11 @@ const sigthingFormApp = (id_session, type_contact) => {
// )
// }
// },
computed: {
species() {
return this.data.map(e=> e.codesp)
},
},
watch: {
data: {
handler() {
......
......@@ -306,5 +306,5 @@ class SightingEditForm(SessionEditAuthMixin, DetailView):
def get_context_data(self, **kwargs):
context = super(SightingEditForm, self).get_context_data(**kwargs)
context["icon"] = "fa fa-eye fa-fw"
context["title"] = "Modification d'une observation"
context["title"] = "Edition des observations"
return context
{% extends 'base_fullwidth_leaflet.html' %}
{% extends 'base_fullwidth.html' %}
{% load i18n static %}
{% block title %}
Observations de la session {{object.name}}
{% endblock %}
{% block content %}
<style>
#sessionSightingEdit .panel-item {
......@@ -10,7 +13,6 @@
#sessionSightingEdit .form-inline>* {
margin: 3px 3px !important;
}
</style>
......@@ -21,10 +23,21 @@
<div id="sessionSightingEditTitle" class="col-12">
<h1><i class="{{ icon | safe }}"></i> {{ title | safe }} <span v-if="initialDataLoaded"
class="pull-right label label-success label-sm">[[data.length]] obs</span></h1>
<ol class="breadcrumb">
<li><a href="{% url 'sights:place_detail' pk=object.place.pk %}">Localité</a> (<span class="text-muted">{{object.place.name}}</span>)</li>
<li><a href="{% url 'sights:session_detail' pk=object.pk %}">Session</a> (<span class="text-muted">{{object.name}} <span class="label label-default">{{object.contact.descr}}</span></span>)</li>
</ol>
<div v-if="errors.length > 0" class="alert alert-danger">
<div v-for="e in errors">
<div v-for="k in Object.keys(e)">
<strong>[[ k ]]</strong>: [[ e[k] ]]
</div>
</div>
</div>
</div>
<div id="sessionSightingEditForm">
<validation-observer tag="form" v-slot="{ invalid, valid }" slim>
<div id="sessionSightingEditFormList" class="col-sm-2 ">
<div id="sessionSightingEditFormList" class="col-sm-4 col-md-2">
<div class="panel btn-group btn-group-justified" role="group" aria-label="...">
<div class="btn-group" role="group">
<span @click="addNewSighting()" class="btn btn-info btn-xs "><i class="fa fa-plus"></i> <strong>Nouveau
......@@ -72,7 +85,7 @@
</div>
</div>
</div>
<div id="sessionSightingEditFormDetails" class="col-sm-10">
<div id="sessionSightingEditFormDetails" class="col-sm-8 col-md-10">
<div v-if="data[selectedItem]" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
......@@ -100,12 +113,10 @@
<validation-provider rules="required" immediate v-slot="{ errors, valid, invalid, classes}">
<div class="form-group" :class='classes'>
<label class="control-label" for="codeSp">Taxon</label>
<v-select class="form-control" id="codeSp" :options="dicts.Specie" :reduce="sp => sp.id" label="codesp" v-model="data[selectedItem].codesp"/>
<specie-select v-model="data[selectedItem].codesp" />
<span v-if='invalid' class="text-danger help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<div class="form-group">
<label class="control-label" for="codeSp">Nombre total</label>
<input id="codeSp" type="number" class="form-control input-sm" placeholder="Nombre total"
......@@ -153,16 +164,9 @@
v-for="(cd, icd) in data[selectedItem].countdetails">
<span class="btn btn-xs pull-right btn-danger" @click="delCountDetail(selectedItem,icd)"><i
class="fa fa-trash"></i></span>
<span v-if="cd.id_countdetail" class="label label-info">#[[cd.id_countdetail]]</span>
<span v-else class="label label-success">New</span>
<span class="label" :class="cd.id_countdetail ? 'label-info':'label-success'">[[cd.id_countdetail ? `#`+cd.id_countdetail: 'New']]</span>
<input type="hidden" class="form-control input-sm" id="id" placeholder="id_sighting"
v-model:title="cd.id_sighting" v-model:content="cd.id_sighting" />
{% comment %} <form id="countdetail-form-block" class="form row" v-for="(cd, icd) in cd.countdetails">
{% endcomment %}
{% comment %} <span>[[icd+1]] - </span>
<span v-if="cd.id_countdetail" class="label label-default">#[[cd.id_countdetail]]</span>
<span v-else class="badge badge-success">New</span> {% endcomment %}
<input type="hidden" id="id" placeholder="id_countdetail" v-model:title="cd.id_countdetail"
v-model:content="cd.id_countdetail" />
<div class="form-group">
......@@ -173,49 +177,26 @@
<validation-provider rules="required" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class='classes'>
<label class="control-label" for="Method">Méthode</label>
<select id="Method" class="form-control input-sm" v-model:title="cd.method"
v-model:content="cd.method" class="form-control">
<option v-for="method in filteredDict(dicts.Method, typeContact)" v-bind:value="method.id">
[[ method.descr ]]
</option>
</select>
<dict-select :options="filteredDict(dicts.Method, typeContact)" v-model="cd.method"/>
<span v-if='invalid' class="help-block text-danger">[[ errors[0] ]]</span>
</div>
</validation-provider>
<div class="col form-group">
<label class="control-label" for="Sex">Sexe</label>
<select id="Sex" class="form-control input-sm" v-model:title="cd.sex" v-model:content="cd.sex"
class="form-control">
<option v-bind:value="null">-</option>
<option v-for="sex in dicts.Sex" v-bind:value="sex.id">
[[ sex.descr ]]
</option>
</select>
<dict-select :options="filteredDict(dicts.Sex)" v-model="cd.sex"/>
</div>
<div class="form-group">
<label class="control-label" for="Age">Age</label>
<select id="Age" class="form-control input-sm" v-model:title="cd.age" v-model:content="cd.age"
class="form-control">
<option v-bind:value="null">-</option>
<option v-for="age in dicts.Age" v-bind:value="age.id">
[[ age.descr ]]
</option>
</select>
<dict-select :options="filteredDict(dicts.Age)" v-model="cd.age"/>
</div>
<validation-provider rules="required" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider v-if="filteredDict(dicts.CountPrecision, typeContact).length > 0" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" class="form-group" :class='classes'>
<label class="control-label" for="Precision">Précision</label>
<select id="Precision" class="form-control input-sm" v-model:title="cd.precision"
v-model:content="cd.precision" class="form-control">
<option v-for="precision in filteredDict(dicts.CountPrecision, typeContact)"
v-bind:value="precision.id">
[[ precision.descr ]]
</option>
</select>
<dict-select :options="filteredDict(dicts.CountPrecision, typeContact)" v-model="cd.precision"/>
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="required|positive" immediate v-slot="{ errors, valid, invalid, classes}"
<validation-provider immediate rules="required|positive" v-slot="{ errors, valid, invalid, classes}"
slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Count">Dénombrement</label>
......@@ -224,76 +205,138 @@
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="required" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider v-if="filteredDict(dicts.CountPrecision, typeContact).length > 0" rules="required" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Unit">Unité</label>
<select id="Unit" class="form-control input-sm" v-model:title="cd.unit" v-model:content="cd.unit"
class="form-control" required>
<option v-for="unit in filteredDict(dicts.CountUnit,typeContact)" v-bind:value="unit.id">
[[ unit.descr ]]
</option>
</select>
<dict-select :options="filteredDict(dicts.CountUnit, typeContact)" v-model="cd.unit"/>
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="AB">Avant-bras</label>
<input type="number" id="AB" class="form-control input-sm" v-model:title="cd.ab"
v-model:content="cd.ab" class="form-control">
v-model:content="cd.ab" class="form-control" min="20" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="D5">Doigt 5</label>
<input type="number" id="D5" class="form-control input-sm" v-model:title="cd.d5"
v-model:content="cd.d5" class="form-control">
v-model:content="cd.d5" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Pouce">Pouce</label>
<input type="number" id="Pouce" class="form-control input-sm" v-model:title="cd.pouce"
v-model:content="cd.pouce" class="form-control">
v-model:content="cd.pouce" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Queue">Queue</label>
<input type="number" id="Queue" class="form-control input-sm" v-model:title="cd.queue"
v-model:content="cd.queue" class="form-control">
v-model:content="cd.queue" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Tibia">Tibia</label>
<input type="number" id="Tibia" class="form-control input-sm" v-model:title="cd.tibia"
v-model:content="cd.tibia" class="form-control">
v-model:content="cd.tibia" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Pied">Pied</label>
<input type="number" id="Pied" class="form-control input-sm" v-model:title="cd.pied"
v-model:content="cd.pied" class="form-control">
v-model:content="cd.pied" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Cm3">cm3</label>
<input type="number" id="Cm3" class="form-control input-sm" v-model:title="cd.pied"
v-model:content="cd.cm3" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Tragus">tragus</label>
<input type="number" id="Tragus" class="form-control input-sm" v-model:title="cd.pied"
v-model:content="cd.tragus" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<validation-provider rules="positive" immediate v-slot="{ errors, valid, invalid, classes}" slim>
<div class="form-group" :class="classes">
<label class="control-label" for="Poids">poids</label>
<input type="number" id="Poids" class="form-control input-sm" v-model:title="cd.pied"
v-model:content="cd.poids" class="form-control" min="0" step="0.1">
<span v-if='invalid' class="help-block">[[ errors[0] ]]</span>
</div>
</validation-provider>
<div v-if="cd.sex === findCondition(dicts.Sex, 'm').id" class="form-group" class="form-group">
<label class="control-label" for="Testicule">Testicule</label>
<dict-select id="Testicule" :options="filteredDict(dicts.BiomTesticule)" v-model="cd.testicule"/>
</div>
<div v-if="cd.sex === findCondition(dicts.Sex, 'm').id" class="form-group" class="form-group">
<label class="control-label" for="Epididyme">Epididyme</label>
<dict-select id="Epididyme" :options="filteredDict(dicts.BiomEpipidyme)" v-model="cd.epididyme"/>
</div>
<div v-if="cd.sex === findCondition(dicts.Sex, 'm').id" class="form-group" class="form-group">
<label class="control-label" for="TuniqVag">Tunique vaginale</label>
<dict-select :options="filteredDict(dicts.BiomTuniqVag)" v-model="cd.tuniq_vag"/>
</div>
<div class="form-group">
<label class="control-label" for="GlandCoul">Couleur des glandes salivaires</label>
<dict-select :options="filteredDict(dicts.BiomGlandCoul)" v-model="cd.gland_coul"/>
</div>
<div class="form-group" >
<label class="control-label" for="GlandTaille">Taille des glandes salivaires</label>
<dict-select :options="filteredDict(dicts.BiomGlandTaille)" v-model="cd.gland_taille"/>
</div>
<div v-if="cd.sex === findCondition(dicts.Sex, 'f').id" class="form-group" >
<label class="control-label" for="Mamal">Etat des mamelles</label>
<dict-select :options="filteredDict(dicts.BiomMamelle)" v-model="cd.mamelle"/>
</div>
<div v-if="cd.sex === findCondition(dicts.Sex, 'f').id" class="form-group" >
<label class="control-label" for="Gestation">Etat de la gestation</label>
<dict-select :options="filteredDict(dicts.BiomGestation)" v-model="cd.gestation"/>
</div>
<div class="form-group" class="form-group" >
<label class="control-label" for="Epiphyse">Epiphyse articulaire</label>
<dict-select :options="filteredDict(dicts.BiomEpiphyse)" v-model="cd.epiphyse"/>
</div>
<div class="form-group" >
<label class="control-label" for="Chinspot">Chinspot</label>
<dict-select :options="filteredDict(dicts.BiomChinspot)" v-model="cd.chinspot"/>
</div>
<div class="form-group" >
<label class="control-label" for="SecualStatus">Usure des dents</label>
<dict-select :options="filteredDict(dicts.BiomDent)" v-model="cd.usure_dent"/>
</div>
<div class="form-group">
<label for="sComment">Commentaire</label>
<textarea id="sComment" class="form-control" placeholder="Commentaire" v-model="cd.comment" class="form-control" rows="3"></textarea>
</div>
</div>
</div>
<div class="panel-footer">
<div class="btn-group text-right">
<button class="btn btn-xs btn-info" @click="addNewCountDetail(selectedItem)">
<div class="btn btn-xs btn-info" @click="addNewCountDetail(selectedItem)">
<i class="fa fa-plus"></i>
<strong>Nouveau dénombrement</strong>
</button>
</div>
</div>
</div>
</div>
......@@ -303,6 +346,8 @@
<div class="btn-group" role="group">
<span class="btn btn-warning btn-xs " @click="showRawData = !showRawData">raw</span>
</div>
<pre v-if="showRawData">[[species]]</pre>
<pre v-if="showRawData">[[data]]</pre>
</div>
......@@ -312,7 +357,7 @@
const sightingDataListUrl = "{% url 'sights:count_detail_api' session=object.pk %}"
const typeContact = "{{object.contact.code}}"
$(document).ready((sightingDataListUrl) => {
$(document).ready(() => {
const vm = new Vue(sigthingFormApp(parseInt("{{object.pk}}"), "{{object.contact.code}}"))
})
......
Markdown is supported
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