mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 09:18:24 +00:00 
			
		
		
		
	Compare commits
	
		
			13 Commits
		
	
	
		
			2.19.0
			...
			issue357_f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | db65134743 | ||
| 7af4c3434e | |||
|  | a09c8ee8af | ||
|  | a312a9463d | ||
|  | 0035128138 | ||
|  | 49cb154672 | ||
|  | 1a7ec9e396 | ||
|  | fa0b9271c2 | ||
|  | c7b9a1a3fe | ||
|  | f1c61a2387 | ||
|  | 8f6a70b240 | ||
|  | 40e4bf953f | ||
|  | 378f3a16fc | 
| @@ -11,7 +11,8 @@ and this project adheres to | ||||
| ## Unreleased | ||||
|  | ||||
| <!-- write down unreleased development here --> | ||||
|  | ||||
| * vuejs: add validation on required fields for AddPerson, Address and Location components | ||||
| * vuejs: treat 422 validation errors in locations and AddPerson components | ||||
|  | ||||
| ## Test releases | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import Location from './components/Location.vue'; | ||||
|  | ||||
| export default { | ||||
|    name: "App", | ||||
|     props: ['hasSocialIssues', 'hasLocation', 'hasPerson'], | ||||
|    props: ['hasSocialIssues', 'hasLocation', 'hasPerson'], | ||||
|    components: { | ||||
|       ConcernedGroups, | ||||
|       SocialIssuesAcc, | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|                     v-model="location" | ||||
|                 > | ||||
|                 </VueMultiselect> | ||||
|                 <new-location v-bind:locations="locations"></new-location> | ||||
|                 <new-location v-bind:availableLocations="availableLocations"></new-location> | ||||
|             </div> | ||||
|         </div> | ||||
|     </teleport> | ||||
|   | ||||
| @@ -18,15 +18,6 @@ | ||||
|                 </template> | ||||
|                 <template v-slot:body> | ||||
|                     <form> | ||||
|                         <div class="form-floating mb-3"> | ||||
|                             <p v-if="errors.length"> | ||||
|                                 <b>{{ $t('activity.errors') }}</b> | ||||
|                                 <ul> | ||||
|                                     <li v-for="error in errors" :key="error">{{ error }}</li> | ||||
|                                 </ul> | ||||
|                             </p> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="form-floating mb-3"> | ||||
|                             <select class="form-select form-select-lg" id="type" required v-model="selectType"> | ||||
|                                 <option selected disabled value="">{{ $t('activity.choose_location_type') }}</option> | ||||
| @@ -62,6 +53,12 @@ | ||||
|                             <input class="form-control form-control-lg" id="email" v-model="inputEmail" placeholder /> | ||||
|                             <label for="email">{{ $t('activity.location_fields.email') }}</label> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="alert alert-warning" v-if="errors.length"> | ||||
|                             <ul> | ||||
|                                 <li v-for="(e, i) in errors" :key="i">{{ e }}</li> | ||||
|                             </ul> | ||||
|                         </div> | ||||
|                     </form> | ||||
|                 </template> | ||||
|                 <template v-slot:footer> | ||||
| @@ -81,7 +78,8 @@ | ||||
| import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue'; | ||||
| import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue"; | ||||
| import { mapState } from "vuex"; | ||||
| import { getLocationTypes, postLocation } from "../../api"; | ||||
| import { getLocationTypes } from "../../api"; | ||||
| import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods'; | ||||
|  | ||||
| export default { | ||||
|     name: "NewLocation", | ||||
| @@ -89,7 +87,7 @@ export default { | ||||
|         Modal, | ||||
|         AddAddress, | ||||
|     }, | ||||
|     props: ['locations'], | ||||
|     props: ['availableLocations'], | ||||
|     data() { | ||||
|         return { | ||||
|             errors: [], | ||||
| @@ -223,7 +221,6 @@ export default { | ||||
|         }, | ||||
|         saveNewLocation() { | ||||
|             if (this.checkForm()) { | ||||
|                 console.log('saveNewLocation', this.selected); | ||||
|                 let body = { | ||||
|                     type: 'location', | ||||
|                     name: this.selected.name, | ||||
| @@ -242,23 +239,28 @@ export default { | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|                 postLocation(body) | ||||
|                     .then( | ||||
|                         location => new Promise(resolve => { | ||||
|                             this.locations.push(location); | ||||
|                             this.$store.dispatch('updateLocation', location); | ||||
|                             resolve(); | ||||
|                             this.modal.showModal = false; | ||||
|                         }) | ||||
|                     ).catch( | ||||
|                         err => { | ||||
|                             this.errors.push(err.message); | ||||
|  | ||||
|                 makeFetch('POST', '/api/1.0/main/location.json', body) | ||||
|                     .then(response => { | ||||
|                          this.$store.dispatch('addAvailableLocationGroup', { | ||||
|                             locationGroup: 'Localisations nouvellement créées', | ||||
|                             locations: [response] | ||||
|                         }); | ||||
|                         this.$store.dispatch('updateLocation', response); | ||||
|                         this.modal.showModal = false; | ||||
|                     }) | ||||
|                     .catch((error) => { | ||||
|                         if (error.name === 'ValidationException') { | ||||
|                             for (let v of error.violations) { | ||||
|                                 this.errors.push(v); | ||||
|                             } | ||||
|                         } else { | ||||
|                             this.errors.push('An error occurred'); | ||||
|                         } | ||||
|                     ); | ||||
|                     }) | ||||
|             }; | ||||
|         }, | ||||
|         submitNewAddress(payload) { | ||||
|             console.log('submitNewAddress', payload); | ||||
|             this.selected.addressId = payload.addressId; | ||||
|             this.addAddress.context.addressId = payload.addressId; | ||||
|             this.addAddress.context.edit = true; | ||||
|   | ||||
| @@ -12,7 +12,11 @@ const hasLocation = document.querySelector('#location') !== null; | ||||
| const hasPerson = document.querySelector('#add-persons') !== null; | ||||
|  | ||||
| const app = createApp({ | ||||
|    template: `<app :hasSocialIssues="hasSocialIssues", :hasLocation="hasLocation", :hasPerson="hasPerson"></app>`, | ||||
|    template: `<app | ||||
|        :hasSocialIssues="hasSocialIssues" | ||||
|        :hasLocation="hasLocation" | ||||
|        :hasPerson="hasPerson" | ||||
|     ></app>`, | ||||
|     data() { | ||||
|        return { | ||||
|            hasSocialIssues, | ||||
|   | ||||
| @@ -240,6 +240,9 @@ const store = createStore({ | ||||
|             }); | ||||
|             commit("updateActionsSelected", payload); | ||||
|         }, | ||||
|         addAvailableLocationGroup({ commit }, payload) { | ||||
|             commit("addAvailableLocationGroup", payload); | ||||
|         }, | ||||
|         addPersonsInvolved({ commit }, payload) { | ||||
|             //console.log('### action addPersonsInvolved', payload.result.type); | ||||
|             switch (payload.result.type) { | ||||
|   | ||||
| @@ -418,3 +418,8 @@ span.item-key { | ||||
|     background-color: #0000000a; | ||||
|     //text-decoration: dotted underline; | ||||
| } | ||||
|  | ||||
| // increase toast message z-index (above all modals) | ||||
| div.v-toast { | ||||
|    z-index: 10000!important; | ||||
| } | ||||
| @@ -85,7 +85,9 @@ const fetchScopes = () => { | ||||
| const ValidationException = (response) => { | ||||
|     const error = {}; | ||||
|     error.name = 'ValidationException'; | ||||
|     error.violations = response.violations.map((violation) => `${violation.title}`); | ||||
|     error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`); | ||||
|     error.titles = response.violations.map((violation) => violation.title); | ||||
|     error.propertyPaths = response.violations.map((violation) => violation.propertyPath); | ||||
|  | ||||
|     return error; | ||||
| } | ||||
|   | ||||
| @@ -98,6 +98,8 @@ | ||||
|                v-bind:defaultz="this.defaultz" | ||||
|                v-bind:entity="this.entity" | ||||
|                v-bind:flag="this.flag" | ||||
|                v-bind:errors="this.errors" | ||||
|                v-bind:checkErrors="this.checkErrors" | ||||
|                @getCities="getCities" | ||||
|                @getReferenceAddresses="getReferenceAddresses"> | ||||
|             </edit-pane> | ||||
| @@ -123,6 +125,8 @@ | ||||
|          v-bind:defaultz="this.defaultz" | ||||
|          v-bind:entity="this.entity" | ||||
|          v-bind:flag="this.flag" | ||||
|          v-bind:errors="this.errors" | ||||
|          v-bind:checkErrors="this.checkErrors" | ||||
|          v-bind:insideModal="false" | ||||
|          @getCities="getCities" | ||||
|          @getReferenceAddresses="getReferenceAddresses"> | ||||
| @@ -256,8 +260,10 @@ export default { | ||||
|             editPane: false, | ||||
|             datePane: false, | ||||
|             loading: false, | ||||
|             success: false | ||||
|             success: false, | ||||
|             dirty: false | ||||
|          }, | ||||
|          errors: [], | ||||
|          defaultz: { | ||||
|             button: { | ||||
|                text: { create: 'add_an_address_title', edit: 'edit_address' }, | ||||
| @@ -529,6 +535,23 @@ export default { | ||||
|          }); | ||||
|       }, | ||||
|  | ||||
|       checkErrors() { | ||||
|          this.errors = []; | ||||
|          if (this.flag.dirty) { | ||||
|             if (this.entity.selected.country === null) { | ||||
|                this.errors.push("Un pays doit être sélectionné."); | ||||
|             } | ||||
|             if (Object.keys(this.entity.selected.city).length === 0) { | ||||
|                this.errors.push("Une ville doit être sélectionnée."); | ||||
|             } | ||||
|             if (!this.entity.selected.isNoAddress) { | ||||
|                if (this.entity.selected.address.street === null || this.entity.selected.address.streetNumber === null) { | ||||
|                   this.errors.push("Une adresse doit être sélectionnée."); | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|       }, | ||||
|  | ||||
|       /* | ||||
|       *   Make form ready for new changes | ||||
|       */ | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|          @search-change="listenInputSearch" | ||||
|          ref="addressSelector" | ||||
|          @select="selectAddress" | ||||
|          @remove="remove" | ||||
|          name="field" | ||||
|          track-by="id" | ||||
|          label="value" | ||||
| @@ -56,7 +57,7 @@ import { searchReferenceAddresses, fetchReferenceAddresses } from '../../api.js' | ||||
| export default { | ||||
|    name: 'AddressSelection', | ||||
|    components: { VueMultiselect }, | ||||
|    props: ['entity', 'context', 'updateMapCenter'], | ||||
|    props: ['entity', 'context', 'updateMapCenter', 'flag', 'checkErrors'], | ||||
|    data() { | ||||
|       return { | ||||
|          value: this.context.edit ? this.entity.address.addressReference : null, | ||||
| @@ -109,6 +110,13 @@ export default { | ||||
|          this.entity.selected.address.streetNumber = value.streetNumber; | ||||
|          this.entity.selected.writeNew.address = false; | ||||
|          this.updateMapCenter(value.point); | ||||
|          this.flag.dirty = true; | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|       remove() { | ||||
|          this.flag.dirty = true; | ||||
|          this.entity.selected.address = {}; | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|       listenInputSearch(query) { | ||||
|          //console.log('listenInputSearch', query, this.isAddressSelectorOpen); | ||||
| @@ -149,6 +157,8 @@ export default { | ||||
|             this.entity.selected.address.street = addr.street; | ||||
|             this.entity.selected.address.streetNumber = addr.number; | ||||
|             this.entity.selected.writeNew.address = true; | ||||
|             this.flag.dirty = true; | ||||
|             this.checkErrors(); | ||||
|          } | ||||
|       }, | ||||
|       splitAddress(address) { | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
|          @search-change="listenInputSearch" | ||||
|          ref="citySelector" | ||||
|          @select="selectCity" | ||||
|          @remove="remove" | ||||
|          name="field" | ||||
|          track-by="id" | ||||
|          label="value" | ||||
| @@ -55,12 +56,12 @@ import { searchCities, fetchCities } from '../../api.js'; | ||||
| export default { | ||||
|    name: 'CitySelection', | ||||
|    components: { VueMultiselect }, | ||||
|    props: ['entity', 'context', 'focusOnAddress', 'updateMapCenter'], | ||||
|    props: ['entity', 'context', 'focusOnAddress', 'updateMapCenter', 'flag', 'checkErrors'], | ||||
|    emits: ['getReferenceAddresses'], | ||||
|    data() { | ||||
|       return { | ||||
|          value: this.context.edit ? this.entity.address.postcode : null, | ||||
|          isLoading: false | ||||
|          isLoading: false, | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
| @@ -123,6 +124,13 @@ export default { | ||||
|          if (value.center) { | ||||
|             this.updateMapCenter(value.center); | ||||
|          } | ||||
|          this.flag.dirty = true; | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|       remove() { | ||||
|          this.flag.dirty = true; | ||||
|          this.entity.selected.city = {}; | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|       listenInputSearch(query) { | ||||
|          if (query.length > 2) { | ||||
|   | ||||
| @@ -12,7 +12,9 @@ | ||||
|          :select-label="$t('multiselect.select_label')" | ||||
|          :deselect-label="$t('multiselect.deselect_label')" | ||||
|          :selected-label="$t('multiselect.selected_label')" | ||||
|          @select="selectCountry"> | ||||
|          @select="selectCountry" | ||||
|          @remove="remove" | ||||
|       > | ||||
|       </VueMultiselect> | ||||
|    </div> | ||||
| </template> | ||||
| @@ -23,7 +25,7 @@ import VueMultiselect from 'vue-multiselect'; | ||||
| export default { | ||||
|    name: 'CountrySelection', | ||||
|    components: { VueMultiselect }, | ||||
|    props: ['context', 'entity'], | ||||
|    props: ['context', 'entity', 'flag', 'checkErrors'], | ||||
|    emits: ['getCities'], | ||||
|    data() { | ||||
|       return { | ||||
| @@ -34,14 +36,13 @@ export default { | ||||
|    }, | ||||
|    computed: { | ||||
|       sortedCountries() { | ||||
|          //console.log('sorted countries'); | ||||
|          const countries = this.entity.loaded.countries; | ||||
|          let sortedCountries = []; | ||||
|          sortedCountries.push(...countries.filter(c => c.countryCode === 'FR')) | ||||
|          sortedCountries.push(...countries.filter(c => c.countryCode === 'BE')) | ||||
|          sortedCountries.push(...countries.filter(c => c.countryCode !== 'FR').filter(c => c.countryCode !== 'BE')) | ||||
|          return sortedCountries; | ||||
|       } | ||||
|       }, | ||||
|    }, | ||||
|    mounted() { | ||||
|       this.init(); | ||||
| @@ -50,6 +51,7 @@ export default { | ||||
|       init() { | ||||
|          if (this.value !== undefined) { | ||||
|             this.selectCountry(this.value); | ||||
|             this.flag.dirty = false; | ||||
|          } | ||||
|       }, | ||||
|       selectCountryByCode(countryCode) { | ||||
| @@ -62,7 +64,13 @@ export default { | ||||
|          //console.log('select country', value); | ||||
|          this.entity.selected.country = value; | ||||
|          this.$emit('getCities', value); | ||||
|       } | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|       remove() { | ||||
|          this.flag.dirty = true; | ||||
|          this.entity.selected.country = null; | ||||
|          this.checkErrors(); | ||||
|       }, | ||||
|  | ||||
|    } | ||||
| }; | ||||
|   | ||||
| @@ -7,6 +7,12 @@ | ||||
|          <span class="sr-only">Loading...</span> | ||||
|       </div> | ||||
|  | ||||
|       <div v-if="errors.length" class="alert alert-warning" > | ||||
|          <ul> | ||||
|             <li v-for="(e, i) in errors" :key="i">{{ e }}</li> | ||||
|          </ul> | ||||
|       </div> | ||||
|  | ||||
|       <h4 class="h3">{{ $t('select_an_address_title') }}</h4> | ||||
|       <div class="row my-3"> | ||||
|          <div class="col-lg-6"> | ||||
| @@ -25,6 +31,8 @@ | ||||
|             <country-selection | ||||
|                v-bind:context="context" | ||||
|                v-bind:entity="entity" | ||||
|                v-bind:flag="flag" | ||||
|                v-bind:checkErrors="checkErrors" | ||||
|                @getCities="$emit('getCities', selected.country)"> | ||||
|             </country-selection> | ||||
|  | ||||
| @@ -33,13 +41,17 @@ | ||||
|                v-bind:context="context" | ||||
|                v-bind:focusOnAddress="focusOnAddress" | ||||
|                v-bind:updateMapCenter="updateMapCenter" | ||||
|                v-bind:flag="flag" | ||||
|                v-bind:checkErrors="checkErrors" | ||||
|                @getReferenceAddresses="$emit('getReferenceAddresses', selected.city)"> | ||||
|             </city-selection> | ||||
|  | ||||
|             <address-selection v-if="!isNoAddress" | ||||
|                v-bind:entity="entity" | ||||
|                v-bind:context="context" | ||||
|                v-bind:updateMapCenter="updateMapCenter"> | ||||
|                v-bind:updateMapCenter="updateMapCenter" | ||||
|                v-bind:flag="flag" | ||||
|                v-bind:checkErrors="checkErrors"> | ||||
|             </address-selection> | ||||
|  | ||||
|          </div> | ||||
| @@ -99,7 +111,9 @@ export default { | ||||
|       'flag', | ||||
|       'entity', | ||||
|       'errorMsg', | ||||
|       'insideModal' | ||||
|       'insideModal', | ||||
|       'errors', | ||||
|       'checkErrors', | ||||
|    ], | ||||
|    emits: ['getCities', 'getReferenceAddresses'], | ||||
|    data() { | ||||
| @@ -128,7 +142,7 @@ export default { | ||||
|          get() { | ||||
|             return this.entity.selected.isNoAddress; | ||||
|          } | ||||
|       } | ||||
|       }, | ||||
|    }, | ||||
|    methods: { | ||||
|       focusOnAddress() { | ||||
|   | ||||
| @@ -90,7 +90,7 @@ export default { | ||||
|       OnTheFlyThirdparty, | ||||
|       OnTheFlyCreate | ||||
|    }, | ||||
|    props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'parent'], | ||||
|    props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'parent', 'canCloseModal'], | ||||
|    emits: ['saveFormOnTheFly'], | ||||
|    data() { | ||||
|       return { | ||||
| @@ -162,7 +162,20 @@ export default { | ||||
|          return 'entity-' + this.type + ' badge-' + this.type; | ||||
|       } | ||||
|    }, | ||||
|    watch: { | ||||
|       canCloseModal: { | ||||
|          handler: function(val, oldVal) { | ||||
|             if (val) { | ||||
|                this.closeModal(); | ||||
|             } | ||||
|          }, | ||||
|          deep: true | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       closeModal() { | ||||
|          this.modal.showModal = false; | ||||
|       }, | ||||
|       openModal() { | ||||
|          //console.log('## OPEN ON THE FLY MODAL'); | ||||
|          //console.log('## type:', this.type, ', action:', this.action); | ||||
| @@ -200,8 +213,6 @@ export default { | ||||
|  | ||||
|          // pass datas to parent | ||||
|          this.$emit('saveFormOnTheFly', { type: type, data: data }); | ||||
|  | ||||
|          this.modal.showModal = false; | ||||
|       }, | ||||
|       buildLocation(id, type) { | ||||
|          if (type === 'person') { | ||||
|   | ||||
| @@ -66,9 +66,10 @@ | ||||
|                <div class="create-button"> | ||||
|                   <on-the-fly | ||||
|                      v-if="query.length >= 3" | ||||
|                      v-bind:buttonText="$t('onthefly.create.button', {q: query})" | ||||
|                      :buttonText="$t('onthefly.create.button', {q: query})" | ||||
|                      action="create" | ||||
|                      @saveFormOnTheFly="saveFormOnTheFly"> | ||||
|                      @saveFormOnTheFly="saveFormOnTheFly" | ||||
|                      :canCloseModal="canCloseOnTheFlyModal"> | ||||
|                   </on-the-fly> | ||||
|                </div> | ||||
|  | ||||
| @@ -91,8 +92,7 @@ import Modal from 'ChillMainAssets/vuejs/_components/Modal'; | ||||
| import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue'; | ||||
| import PersonSuggestion from './AddPersons/PersonSuggestion'; | ||||
| import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons'; | ||||
| import { postPerson } from "ChillPersonAssets/vuejs/_api/OnTheFly"; | ||||
| import { postThirdparty } from "ChillThirdPartyAssets/vuejs/_api/OnTheFly"; | ||||
| import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods'; | ||||
|  | ||||
| export default { | ||||
|    name: 'AddPersons', | ||||
| @@ -120,7 +120,8 @@ export default { | ||||
|             suggested: [], | ||||
|             selected: [], | ||||
|             priorSuggestion: {} | ||||
|          } | ||||
|          }, | ||||
|          canCloseOnTheFlyModal: false | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
| @@ -267,22 +268,36 @@ export default { | ||||
|       saveFormOnTheFly({ type, data }) { | ||||
|          console.log('saveFormOnTheFly from addPersons, type', type, ', data', data); | ||||
|          if (type === 'person') { | ||||
|             console.log('type person with', data); | ||||
|             postPerson(data) | ||||
|                .then(person => new Promise((resolve, reject) => { | ||||
|                   console.log('onthefly create: post person', person); | ||||
|                   this.newPriorSuggestion(person); | ||||
|                   resolve(); | ||||
|                })); | ||||
|             makeFetch('POST', '/api/1.0/person/person.json', data) | ||||
|                .then(response => { | ||||
|                   this.newPriorSuggestion(response); | ||||
|                   this.canCloseOnTheFlyModal = true; | ||||
|                }) | ||||
|                .catch((error) => { | ||||
|                   if (error.name === 'ValidationException') { | ||||
|                      for (let v of error.violations) { | ||||
|                          this.$toast.open({message: v }); | ||||
|                      } | ||||
|                   } else { | ||||
|                       this.$toast.open({message: 'An error occurred'}); | ||||
|                   } | ||||
|                }) | ||||
|          } | ||||
|          else if (type === 'thirdparty') { | ||||
|             console.log('type thirdparty with', data); | ||||
|             postThirdparty(data) | ||||
|                .then(thirdparty => new Promise((resolve, reject) => { | ||||
|                   console.log('onthefly create: post thirdparty', thirdparty); | ||||
|                   this.newPriorSuggestion(thirdparty); | ||||
|                   resolve(); | ||||
|                })); | ||||
|             makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data) | ||||
|                .then(response => { | ||||
|                   this.newPriorSuggestion(response); | ||||
|                   this.canCloseOnTheFlyModal = true; | ||||
|                }) | ||||
|                .catch((error) => { | ||||
|                   if (error.name === 'ValidationException') { | ||||
|                      for (let v of error.violations) { | ||||
|                          this.$toast.open({message: v }); | ||||
|                      } | ||||
|                   } else { | ||||
|                       this.$toast.open({message: 'An error occurred'}); | ||||
|                   } | ||||
|                }) | ||||
|          } | ||||
|       } | ||||
|    }, | ||||
|   | ||||
| @@ -22,24 +22,45 @@ | ||||
| <div v-else-if="action === 'edit' || action === 'create'"> | ||||
|  | ||||
|    <div class="form-floating mb-3"> | ||||
|       <input class="form-control form-control-lg" id="lastname" v-model="lastName" v-bind:placeholder="$t('person.lastname')" /> | ||||
|       <input | ||||
|           class="form-control form-control-lg" | ||||
|           id="lastname" | ||||
|           v-model="lastName" | ||||
|           :placeholder="$t('person.lastname')" | ||||
|           @change="checkErrors" | ||||
|       /> | ||||
|       <label for="lastname">{{ $t('person.lastname') }}</label> | ||||
|    </div> | ||||
|  | ||||
|    <div class="form-floating mb-3"> | ||||
|       <input class="form-control form-control-lg" id="firstname" v-model="firstName" v-bind:placeholder="$t('person.firstname')" /> | ||||
|       <input | ||||
|           class="form-control form-control-lg" | ||||
|           id="firstname" | ||||
|           v-model="firstName" | ||||
|           :placeholder="$t('person.firstname')" | ||||
|           @change="checkErrors" | ||||
|       /> | ||||
|       <label for="firstname">{{ $t('person.firstname') }}</label> | ||||
|    </div> | ||||
|  | ||||
|    <div v-for="(a) in config.altNames" :key="a.key" class="form-floating mb-3"> | ||||
|       <input class="form-control form-control-lg" :id="a.key" @input="onAltNameInput" /> | ||||
|       <input | ||||
|           class="form-control form-control-lg" | ||||
|           :id="a.key" | ||||
|           @input="onAltNameInput" | ||||
|       /> | ||||
|       <label :for="a.key">{{ a.labels.fr }}</label> | ||||
|    </div> | ||||
|  | ||||
|    <!--  TODO fix placeholder if undefined | ||||
|    --> | ||||
|    <div class="form-floating mb-3"> | ||||
|       <select class="form-select form-select-lg" id="gender" v-model="gender"> | ||||
|       <select | ||||
|          class="form-select form-select-lg" | ||||
|          id="gender" | ||||
|          v-model="gender" | ||||
|          @change="checkErrors" | ||||
|          > | ||||
|          <option selected disabled >{{ $t('person.gender.placeholder') }}</option> | ||||
|          <option value="woman">{{ $t('person.gender.woman') }}</option> | ||||
|          <option value="man">{{ $t('person.gender.man') }}</option> | ||||
| @@ -62,8 +83,8 @@ | ||||
|       <span class="input-group-text" id="phonenumber"><i class="fa fa-fw fa-phone"></i></span> | ||||
|       <input class="form-control form-control-lg" | ||||
|          v-model="phonenumber" | ||||
|          v-bind:placeholder="$t('person.phonenumber')" | ||||
|          v-bind:aria-label="$t('person.phonenumber')" | ||||
|          :placeholder="$t('person.phonenumber')" | ||||
|          :aria-label="$t('person.phonenumber')" | ||||
|          aria-describedby="phonenumber" /> | ||||
|    </div> | ||||
|  | ||||
| @@ -71,8 +92,8 @@ | ||||
|       <span class="input-group-text" id="mobilenumber"><i class="fa fa-fw fa-mobile"></i></span> | ||||
|       <input class="form-control form-control-lg" | ||||
|          v-model="mobilenumber" | ||||
|          v-bind:placeholder="$t('person.mobilenumber')" | ||||
|          v-bind:aria-label="$t('person.mobilenumber')" | ||||
|          :placeholder="$t('person.mobilenumber')" | ||||
|          :aria-label="$t('person.mobilenumber')" | ||||
|          aria-describedby="mobilenumber" /> | ||||
|    </div> | ||||
|  | ||||
| @@ -80,11 +101,17 @@ | ||||
|       <span class="input-group-text" id="email"><i class="fa fa-fw fa-at"></i></span> | ||||
|       <input class="form-control form-control-lg" | ||||
|          v-model="email" | ||||
|          v-bind:placeholder="$t('person.email')" | ||||
|          v-bind:aria-label="$t('person.email')" | ||||
|          :placeholder="$t('person.email')" | ||||
|          :aria-label="$t('person.email')" | ||||
|          aria-describedby="email" /> | ||||
|    </div> | ||||
|  | ||||
|    <div class="alert alert-warning" v-if="errors.length"> | ||||
|      <ul> | ||||
|        <li v-for="(e, i) in errors" :key="i">{{ e }}</li> | ||||
|      </ul> | ||||
|    </div> | ||||
|  | ||||
| </div> | ||||
| </template> | ||||
|  | ||||
| @@ -108,6 +135,7 @@ export default { | ||||
|          config: { | ||||
|             altNames: [] | ||||
|          }, | ||||
|          errors: [] | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
| @@ -183,6 +211,18 @@ export default { | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       checkErrors(e) { | ||||
|          this.errors = []; | ||||
|          if (!this.person.lastName) { | ||||
|              this.errors.push("Le nom ne doit pas être vide."); | ||||
|          } | ||||
|          if (!this.person.firstName) { | ||||
|              this.errors.push("Le prénom ne doit pas être vide."); | ||||
|          } | ||||
|          if (!this.person.gender) { | ||||
|              this.errors.push("Le genre doit être renseigné"); | ||||
|          } | ||||
|       }, | ||||
|       loadData() { | ||||
|          getPerson(this.id) | ||||
|             .then(person => new Promise((resolve, reject) => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user