mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	fix conflict when merging _77_address_household into master
This commit is contained in:
		| @@ -277,7 +277,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_HEAD => true | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                                 Request::METHOD_PATCH => true | ||||
|                             ] | ||||
|                         ], | ||||
|                     ] | ||||
| @@ -319,7 +320,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, | ||||
|                         '_entity' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_HEAD => true | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                                 Request::METHOD_POST => true, | ||||
|                             ] | ||||
|                         ], | ||||
|                     ] | ||||
|   | ||||
| @@ -26,7 +26,7 @@ class PostalCode | ||||
|      * @ORM\Id | ||||
|      * @ORM\Column(name="id", type="integer") | ||||
|      * @ORM\GeneratedValue(strategy="AUTO") | ||||
|      * @groups({"read"}) | ||||
|      * @groups({"write", "read"}) | ||||
|      */ | ||||
|     private $id; | ||||
|  | ||||
| @@ -34,7 +34,7 @@ class PostalCode | ||||
|      * @var string | ||||
|      * | ||||
|      * @ORM\Column(type="string", length=255, name="label") | ||||
|      * @groups({"read"}) | ||||
|      * @groups({"write", "read"}) | ||||
|      */ | ||||
|     private $name; | ||||
|  | ||||
| @@ -42,7 +42,7 @@ class PostalCode | ||||
|      * @var string | ||||
|      * | ||||
|      * @ORM\Column(type="string", length=100) | ||||
|      * @groups({"read"}) | ||||
|      * @groups({"write", "read"}) | ||||
|      */ | ||||
|     private $code; | ||||
|  | ||||
| @@ -50,10 +50,17 @@ class PostalCode | ||||
|      * @var Country | ||||
|      * | ||||
|      * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Country") | ||||
|      * @groups({"read"}) | ||||
|      * @groups({"write", "read"}) | ||||
|      */ | ||||
|     private $country; | ||||
|  | ||||
|     /** | ||||
|      * @var integer | ||||
|      * | ||||
|      * @ORM\Column(name="origin", type="integer", nullable=true) | ||||
|      * @groups({"write", "read"}) | ||||
|      */ | ||||
|     private $origin = 0; | ||||
|  | ||||
|     /** | ||||
|      * Get id | ||||
| @@ -65,6 +72,32 @@ class PostalCode | ||||
|         return $this->id; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Set origin | ||||
|      * | ||||
|      * @param int $origin | ||||
|      * | ||||
|      * @return PostalCode | ||||
|      */ | ||||
|     public function setOrigin($origin) | ||||
|     { | ||||
|         $this->origin = $origin; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get origin | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getOrigin() | ||||
|     { | ||||
|         return $this->origin; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Set name | ||||
|      * | ||||
|   | ||||
| @@ -248,6 +248,9 @@ div.address_form { | ||||
|          display: flex; | ||||
|          flex-direction: column; | ||||
|          flex-grow: 1; | ||||
|          div.custom-address, div.custom-postcode { | ||||
|              padding: 12px; | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       div.address_form__select__map { | ||||
| @@ -255,13 +258,20 @@ div.address_form { | ||||
|          div#address_map { | ||||
|             height:400px; | ||||
|             width:400px; | ||||
|             input { | ||||
|                border: 1px solid #999; | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    div.address_form__more { | ||||
|  | ||||
|       & > div { | ||||
|          display: flex; | ||||
|          & > label { | ||||
|             width: 30%; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,33 +1,73 @@ | ||||
| <template> | ||||
|  | ||||
|    <div v-if="address.address"> | ||||
|       {{ address.address.street }}, {{ address.address.streetNumber }} | ||||
|    <div class='person__address__create'> | ||||
|       <div> | ||||
|          <h2 v-if="!edit">{{ $t('create_a_new_address') }}</h2> | ||||
|          <h2 v-else>{{ $t('edit_a_new_address') }}</h2> | ||||
|          <add-address | ||||
|             @addNewAddress="addNewAddress"> | ||||
|          </add-address> | ||||
|       </div> | ||||
|  | ||||
|       <div> | ||||
|          <show-address | ||||
|             v-if="address" | ||||
|             v-bind:address="address"> | ||||
|          </show-address> | ||||
|       </div> | ||||
|    </div> | ||||
|    <div v-if="address.city"> | ||||
|       {{ address.city.code }} {{ address.city.name }} | ||||
|    </div> | ||||
|    <div v-if="address.country"> | ||||
|       {{ address.country.name }} | ||||
|    <div v-if="!edit" class='person__address__valid'> | ||||
|       <h2>{{ $t('date') }}</h2> | ||||
|       <input | ||||
|          type="date" | ||||
|          name="validFrom" | ||||
|          :placeholder="$t('validFrom')" | ||||
|          v-model="validFrom"/> | ||||
|       <div v-if="errors.length > 0"> | ||||
|          {{ errors }} | ||||
|       </div> | ||||
|    </div> | ||||
|  | ||||
|    <div> | ||||
|       <ul class="record_actions sticky-form-buttons"> | ||||
|          <li class="cancel"> | ||||
|             <a :href=backUrl class="sc-button bt-cancel">{{ $t('back_to_the_list') }}</a> | ||||
|          </li> | ||||
|          <li v-if="!edit"> | ||||
|             <button type="submit" class="sc-button bt-update centered" @click="addToPerson"> | ||||
|                {{ $t('add_an_address_to_person') }} | ||||
|             </button> | ||||
|          </li> | ||||
|       </ul> | ||||
|    </div> | ||||
|  | ||||
|    <add-address | ||||
|       @addNewAddress="addNewAddress"> | ||||
|    </add-address> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex'; | ||||
|  | ||||
| import AddAddress from '../_components/AddAddress.vue'; | ||||
| import ShowAddress from '../_components/ShowAddress.vue'; | ||||
|  | ||||
| export default { | ||||
|    name: 'App', | ||||
|    components: { | ||||
|       AddAddress | ||||
|       AddAddress, | ||||
|       ShowAddress | ||||
|    }, | ||||
|    data() { | ||||
|       return { | ||||
|          edit: window.mode === 'edit', | ||||
|          personId: window.personId, | ||||
|          addressId: window.addressId, | ||||
|          backUrl: `/fr/person/${window.personId}/address/list`, //TODO better way to pass this | ||||
|          validFrom: new Date().toISOString().split('T')[0] | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
|       address() { | ||||
|          return this.$store.state.address; | ||||
|       }, | ||||
|       errors() { | ||||
|          return this.$store.state.errorMsg; | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
| @@ -36,9 +76,9 @@ export default { | ||||
|  | ||||
|          let newAddress = { | ||||
|             'isNoAddress': address.isNoAddress, | ||||
|             'street': address.selected.address.street, | ||||
|             'streetNumber': address.selected.address.streetNumber, | ||||
|             'postcode': {'id': address.selected.city.id }, | ||||
|             'street': address.isNoAddress ? '' : address.street, | ||||
|             'streetNumber': address.isNoAddress ? '' : address.streetNumber, | ||||
|             'postcode': {'id': address.selected.city.id}, | ||||
|             'floor': address.floor, | ||||
|             'corridor': address.corridor, | ||||
|             'steps': address.steps, | ||||
| @@ -49,12 +89,47 @@ export default { | ||||
|          }; | ||||
|  | ||||
|          if (address.selected.address.point !== undefined){ | ||||
|             newAddress = Object.assign(newAddress, {'point': address.selected.address.point.coordinates}); | ||||
|             newAddress = Object.assign(newAddress, { | ||||
|                'point': address.selected.address.point.coordinates | ||||
|             }); | ||||
|          } | ||||
|  | ||||
|          if (address.writeNewPostalCode){ | ||||
|             let newPostalCode = address.newPostalCode; | ||||
|             newPostalCode = Object.assign(newPostalCode, { | ||||
|                 'country': {'id': address.selected.country.id }, | ||||
|             }); | ||||
|             newAddress = Object.assign(newAddress, { | ||||
|                'newPostalCode': newPostalCode | ||||
|             }); | ||||
|          } | ||||
|  | ||||
|          if (this.edit){ | ||||
|             this.$store.dispatch('updateAddress', { | ||||
|                addressId: this.addressId, | ||||
|                newAddress: newAddress | ||||
|             }); | ||||
|          } else { | ||||
|             this.$store.dispatch('addAddress', newAddress); | ||||
|          } | ||||
|  | ||||
|          this.$store.dispatch('addAddress', newAddress); | ||||
|          modal.showModal = false; | ||||
|       }, | ||||
|       addToPerson() { | ||||
|          this.$store.dispatch('addDateToAddressAndAddressToPerson', { | ||||
|             personId: this.personId, | ||||
|             addressId: this.$store.state.address.address_id, | ||||
|             body: { validFrom: {datetime: `${this.validFrom}T00:00:00+0100`}} | ||||
|          }) | ||||
|       }, | ||||
|       getEditAddress() { | ||||
|          this.$store.dispatch('getEditAddress', this.addressId); | ||||
|       } | ||||
|    } | ||||
|    }, | ||||
|    mounted() { | ||||
|       if (this.edit) { | ||||
|          this.getEditAddress(); | ||||
|       } | ||||
|    }, | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -1,20 +1,32 @@ | ||||
| const addressMessages = { | ||||
|    fr: { | ||||
|       add_an_address_title: 'Ajouter une adresse', | ||||
|       add_an_address_title: 'Créer une adresse', | ||||
|       edit_an_address_title: 'Modifier une adresse', | ||||
|       create_a_new_address: 'Créer une nouvelle adresse', | ||||
|       edit_a_new_address: 'Modifier l\'adresse', | ||||
|       select_an_address_title: 'Sélectionner une adresse', | ||||
|       fill_an_address: 'Compléter l\'adresse', | ||||
|       select_country: 'Choisir le pays', | ||||
|       select_city: 'Choisir une localité', | ||||
|       select_address: 'Choisir une adresse', | ||||
|       create_address: 'Appuyer sur "Entrée" pour créer une nouvelle adresse', | ||||
|       create_address: 'Adresse inconnue. Cliquez ici pour créer une nouvelle adresse', | ||||
|       isNoAddress: 'Pas d\'adresse complète', | ||||
|       street: 'Nom de rue', | ||||
|       streetNumber: 'Numéro', | ||||
|       floor: 'Étage', | ||||
|       corridor: 'Couloir', | ||||
|       steps: 'Escalier', | ||||
|       flat: 'Appartement', | ||||
|       buildingName: 'Nom du batiment', | ||||
|       extra: 'Complément d\'adresse', | ||||
|       distribution: 'Service particulier de distribution' | ||||
|       distribution: 'Service particulier de distribution', | ||||
|       create_postal_code: 'Localité inconnue. Cliquez ici pour créer une nouvelle localité', | ||||
|       postalCode_name: 'Nom de la localité', | ||||
|       postalCode_code: 'Code postal de la localité', | ||||
|       date: 'Date de la nouvelle adresse', | ||||
|       add_an_address_to_person: 'Ajouter l\'adresse à la personne', | ||||
|       validFrom: 'Date de la nouvelle adresse', | ||||
|       back_to_the_list: 'Retour à la liste' | ||||
|    } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import 'es6-promise/auto'; | ||||
| import { createStore } from 'vuex'; | ||||
|  | ||||
| import { postAddress } from '../../_api/AddAddress' | ||||
| import { patchAddress, postAddress, postPostalCode, postAddressToPerson, getAddress } from '../../_api/AddAddress' | ||||
|  | ||||
| const debug = process.env.NODE_ENV !== 'production'; | ||||
|  | ||||
| @@ -9,6 +9,8 @@ const store = createStore({ | ||||
|    strict: debug, | ||||
|    state: { | ||||
|       address: {}, | ||||
|       editAddress: {}, //TODO or should be address? | ||||
|       person: {}, | ||||
|       errorMsg: [] | ||||
|    }, | ||||
|    getters: { | ||||
| @@ -20,25 +22,119 @@ const store = createStore({ | ||||
|       addAddress(state, address) { | ||||
|          console.log('@M addAddress address', address); | ||||
|          state.address = address; | ||||
|       } | ||||
|       }, | ||||
|       updateAddress(state, address) { | ||||
|          console.log('@M updateAddress address', address); | ||||
|          state.address = address; | ||||
|       }, | ||||
|       addAddressToPerson(state, person) { | ||||
|          console.log('@M addAddressToPerson person', person); | ||||
|          state.person = person; | ||||
|       }, | ||||
|       addDateToAddress(state, validFrom) { | ||||
|          console.log('@M addDateToAddress address.validFrom', validFrom); | ||||
|          state.validFrom = validFrom; | ||||
|       }, | ||||
|       getEditAddress(state, address) { | ||||
|          console.log('@M getEditAddress address', address); | ||||
|          state.editAddress = address; | ||||
|       }, | ||||
|    }, | ||||
|    actions: { | ||||
|       addAddress({ commit }, payload) { | ||||
|          console.log('@A addAddress payload', payload); | ||||
|          //commit('addAddress', payload); // à remplacer par la suite | ||||
|  | ||||
|          //fetch POST qui envoie l'adresse, et récupère la confirmation que c'est ok. | ||||
|          //La confirmation est l'adresse elle-même. | ||||
|          if('newPostalCode' in payload){ | ||||
|             let postalCodeBody = payload.newPostalCode; | ||||
|             postalCodeBody = Object.assign(postalCodeBody, {'origin': 3}); | ||||
|             postPostalCode(postalCodeBody) | ||||
|                .then(postalCode => { | ||||
|                   let body = payload; | ||||
|                   body.postcode = {'id': postalCode.id}, | ||||
|                   postAddress(body) | ||||
|                      .then(address => new Promise((resolve, reject) => { | ||||
|                         commit('addAddress', address); | ||||
|                         resolve(); | ||||
|                      })) | ||||
|                      .catch((error) => { | ||||
|                         commit('catchError', error); | ||||
|                      }); | ||||
|                }) | ||||
|  | ||||
|          postAddress(payload) | ||||
|          } else { | ||||
|             postAddress(payload) | ||||
|                .then(address => new Promise((resolve, reject) => { | ||||
|                   commit('addAddress', address); | ||||
|                   resolve(); | ||||
|                })) | ||||
|                .catch((error) => { | ||||
|                   commit('catchError', error); | ||||
|                }); | ||||
|          } | ||||
|       }, | ||||
|       addDateToAddressAndAddressToPerson({ commit }, payload) { | ||||
|          console.log('@A addDateToAddressAndAddressToPerson payload', payload); | ||||
|  | ||||
|          patchAddress(payload.addressId, payload.body) | ||||
|             .then(address => new Promise((resolve, reject) => { | ||||
|                commit('addAddress', address); | ||||
|                commit('addDateToAddress', address.validFrom); | ||||
|                resolve(); | ||||
|             })) | ||||
|             }).then( | ||||
|                postAddressToPerson(payload.personId, payload.addressId) | ||||
|                   .then(person => new Promise((resolve, reject) => { | ||||
|                      commit('addAddressToPerson', person); | ||||
|                      resolve(); | ||||
|                })) | ||||
|                .catch((error) => { | ||||
|                   commit('catchError', error); | ||||
|                }) | ||||
|             )) | ||||
|             .catch((error) => { | ||||
|                commit('catchError', error); | ||||
|             }); | ||||
|       } | ||||
|       }, | ||||
|       updateAddress({ commit }, payload) { | ||||
|          console.log('@A updateAddress payload', payload); | ||||
|  | ||||
|          if('newPostalCode' in payload.newAddress){ // TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode | ||||
|             let postalCodeBody = payload.newAddress.newPostalCode; | ||||
|             postalCodeBody = Object.assign(postalCodeBody, {'origin': 3}); | ||||
|             postPostalCode(postalCodeBody) | ||||
|                .then(postalCode => { | ||||
|                   let body = payload.newAddress; | ||||
|                   body.postcode = {'id': postalCode.id }, | ||||
|                   patchAddress(payload.addressId, body) | ||||
|                      .then(address => new Promise((resolve, reject) => { | ||||
|                         commit('updateAddress', address); | ||||
|                         resolve(); | ||||
|                      })) | ||||
|                      .catch((error) => { | ||||
|                         commit('catchError', error); | ||||
|                      }); | ||||
|                }) | ||||
|  | ||||
|          } else { | ||||
|             patchAddress(payload.addressId, payload.newAddress) | ||||
|                .then(address => new Promise((resolve, reject) => { | ||||
|                   commit('updateAddress', address); | ||||
|                   resolve(); | ||||
|                })) | ||||
|                .catch((error) => { | ||||
|                   commit('catchError', error); | ||||
|                }); | ||||
|          } | ||||
|       }, | ||||
|       getEditAddress({ commit }, payload) { | ||||
|          console.log('@A getEditAddress payload', payload); | ||||
|  | ||||
|          getAddress(payload).then(address => new Promise((resolve, reject) => { | ||||
|             commit('getEditAddress', address); | ||||
|             resolve(); | ||||
|          })) | ||||
|          .catch((error) => { | ||||
|             commit('catchError', error); | ||||
|          }); | ||||
|       }, | ||||
|    } | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -36,7 +36,6 @@ const fetchCities = (country) => { | ||||
| */ | ||||
| const fetchReferenceAddresses = (postalCode) => { | ||||
|     console.log('<<< fetching references addresses for', postalCode); | ||||
|    //TODO deal with huge number of addresses... we should do suggestion... | ||||
|     const url = `/api/1.0/main/address-reference.json?item_per_page=1000&postal_code=${postalCode.id}`; | ||||
|     return fetch(url) | ||||
|        .then(response => { | ||||
| @@ -45,16 +44,75 @@ const fetchReferenceAddresses = (postalCode) => { | ||||
|        }); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_address_reference__index | ||||
| * method GET, get AddressReference Object | ||||
| * @returns {Promise} a promise containing all AddressReference objects filtered with postal code | ||||
| */ | ||||
| const fetchAddresses = () => { | ||||
|    console.log('<<< fetching addresses'); | ||||
|   //TODO deal with huge number of addresses... we should do suggestion... | ||||
|    const url = `/api/1.0/main/address.json?item_per_page=1000`; | ||||
|    return fetch(url) | ||||
|       .then(response => { | ||||
|          if (response.ok) { return response.json(); } | ||||
|          throw Error('Error with request resource response'); | ||||
|       }); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_address__entity__create | ||||
| * method POST, post Address Object | ||||
| * @returns {Promise} | ||||
| */ | ||||
| const postAddress = (address) => { | ||||
|    console.log(address); | ||||
|    const url = `/api/1.0/main/address.json?`; | ||||
|    const body = address; | ||||
|  | ||||
|    return fetch(url, { | ||||
|       method: 'POST', | ||||
|       headers: { | ||||
|          'Content-Type': 'application/json;charset=utf-8' | ||||
|       }, | ||||
|       body: JSON.stringify(body) | ||||
|    }).then(response => { | ||||
|       if (response.ok) { return response.json(); } | ||||
|       throw Error('Error with request resource response'); | ||||
|    }); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_address__entity__create | ||||
| * method PATCH, patch Address Instance | ||||
| * | ||||
| *  @id     integer - id of address | ||||
| *  @body   Object - dictionary with changes to post | ||||
| */ | ||||
| const patchAddress = (id, body) => { | ||||
|    const url = `/api/1.0/main/address/${id}.json`; | ||||
|    return fetch(url, { | ||||
|          method: 'PATCH', | ||||
|          headers: { | ||||
|            'Content-Type': 'application/json;charset=utf-8' | ||||
|          }, | ||||
|          body: JSON.stringify(body) | ||||
|       }) | ||||
|       .then(response => { | ||||
|          if (response.ok) { return response.json(); } | ||||
|          throw Error('Error with request resource response'); | ||||
|       }); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_postal_code__entity_create | ||||
| * method POST, post Postal Code Object | ||||
| * @returns {Promise} | ||||
| */ | ||||
| const postPostalCode = (postalCode) => { | ||||
|    const url = `/api/1.0/main/postal-code.json?`; | ||||
|    const body = postalCode; | ||||
|  | ||||
|    return fetch(url, { | ||||
|       method: 'POST', | ||||
|       headers: { | ||||
| @@ -67,9 +125,55 @@ const postAddress = (address) => { | ||||
|    }); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_person_address | ||||
| * method POST, post Person instance | ||||
| * | ||||
| *  @id     integer - id of Person | ||||
| *  @body   Object - dictionary with changes to post | ||||
| */ | ||||
| const postAddressToPerson = (personId, addressId) => { | ||||
|    console.log(personId); | ||||
|    console.log(addressId); | ||||
|    const body = { | ||||
|       'id': addressId | ||||
|    }; | ||||
|    const url = `/api/1.0/person/person/${personId}/address.json` | ||||
|    return fetch(url, { | ||||
|          method: 'POST', | ||||
|          headers: {'Content-Type': 'application/json;charset=utf-8'}, | ||||
|          body: JSON.stringify(body) | ||||
|       }) | ||||
|       .then(response => { | ||||
|          if (response.ok) { return response.json(); } | ||||
|          throw Error('Error with request resource response'); | ||||
|       }); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| * Endpoint chill_api_single_address__index | ||||
| * method GET, get Address Object | ||||
| * @params {id} the address id | ||||
| * @returns {Promise} a promise containing a Address object | ||||
| */ | ||||
| const getAddress = (id) => { | ||||
|    console.log('<<< get address'); | ||||
|    const url = `/api/1.0/main/address/${id}.json`; | ||||
|    return fetch(url) | ||||
|       .then(response => { | ||||
|          if (response.ok) { return response.json(); } | ||||
|          throw Error('Error with request resource response'); | ||||
|       }); | ||||
| }; | ||||
|  | ||||
| export { | ||||
|    fetchCountries, | ||||
|    fetchCities, | ||||
|    fetchReferenceAddresses, | ||||
|    postAddress | ||||
|    fetchAddresses, | ||||
|    postAddress, | ||||
|    patchAddress, | ||||
|    postPostalCode, | ||||
|    postAddressToPerson, | ||||
|    getAddress | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| <template> | ||||
|    <button class="sc-button bt-create centered mt-4" @click="openModal"> | ||||
|    <button v-if="!edit" class="sc-button bt-create mt-4" @click="openModal"> | ||||
|       {{ $t('add_an_address_title') }} | ||||
|    </button> | ||||
|    <button v-else class="sc-button bt-create mt-4" @click="openModal"> | ||||
|       {{ $t('edit_an_address_title') }} | ||||
|    </button> | ||||
|  | ||||
|    <teleport to="body"> | ||||
|       <modal v-if="modal.showModal" | ||||
| @@ -9,7 +12,8 @@ | ||||
|          @close="modal.showModal = false"> | ||||
|  | ||||
|          <template v-slot:header> | ||||
|             <h3 class="modal-title">{{ $t('add_an_address_title') }}</h3> | ||||
|             <h3 v-if="!edit" class="modal-title">{{ $t('add_an_address_title') }}</h3> | ||||
|             <h3 v-if="edit" class="modal-title">{{ $t('edit_an_address_title') }}</h3> | ||||
|          </template> | ||||
|  | ||||
|          <template v-slot:body> | ||||
| @@ -42,6 +46,7 @@ | ||||
|                      </city-selection> | ||||
|  | ||||
|                      <address-selection | ||||
|                         v-if="!isNoAddress" | ||||
|                         v-bind:address="address" | ||||
|                         v-bind:updateMapCenter="updateMapCenter"> | ||||
|                      </address-selection> | ||||
| @@ -100,11 +105,14 @@ export default { | ||||
|    emits: ['addNewAddress'], | ||||
|    data() { | ||||
|       return { | ||||
|          edit: window.mode === 'edit', | ||||
|          modal: { | ||||
|             showModal: false, | ||||
|             modalDialogClass: "modal-dialog-scrollable modal-xl" | ||||
|          }, | ||||
|          address: { | ||||
|             writeNewAddress: false, | ||||
|             writeNewPostalCode: false, | ||||
|             loaded: { | ||||
|                countries: [], | ||||
|                cities: [], | ||||
| @@ -115,11 +123,17 @@ export default { | ||||
|                city: {}, | ||||
|                address: {}, | ||||
|             }, | ||||
|             newPostalCode: { | ||||
|                code: null, | ||||
|                name: null | ||||
|             }, | ||||
|             addressMap: { | ||||
|                center : [48.8589, 2.3469], // Note: LeafletJs demands [lat, lon] cfr https://macwright.com/lonlat/ | ||||
|                zoom: 12 | ||||
|             }, | ||||
|             isNoAddress: false, | ||||
|             street: null, | ||||
|             streetNumber: null, | ||||
|             floor: null, | ||||
|             corridor: null, | ||||
|             steps: null, | ||||
| @@ -167,8 +181,8 @@ export default { | ||||
|       getCities(country) { | ||||
|          console.log('getCities for', country.name); | ||||
|          fetchCities(country).then(cities => new Promise((resolve, reject) => { | ||||
|             this.address.loaded.cities = cities.results; | ||||
|             resolve() | ||||
|             this.address.loaded.cities = cities.results.filter(c => c.origin !== 3); // filter out user-defined cities | ||||
|             resolve(); | ||||
|          })) | ||||
|          .catch((error) => { | ||||
|             this.errorMsg.push(error.message); | ||||
| @@ -198,6 +212,23 @@ export default { | ||||
|          this.address.loaded.cities = []; | ||||
|          this.address.selected.city = {}; | ||||
|          this.address.selected.country = {}; | ||||
|          this.address.isNoAddress = this.edit ? this.$store.state.editAddress.isNoAddress: false;; | ||||
|          this.address.street = this.edit ? this.$store.state.editAddress.street: null; | ||||
|          this.address.streetNumber = this.edit ? this.$store.state.editAddress.streetNumber: null; | ||||
|          this.address.floor = this.edit ? this.$store.state.editAddress.floor: null; | ||||
|          this.address.corridor = this.edit ? this.$store.state.editAddress.corridor: null; | ||||
|          this.address.steps = this.edit ? this.$store.state.editAddress.steps: null; | ||||
|          this.address.flat = this.edit ? this.$store.state.editAddress.flat: null; | ||||
|          this.address.buildingName = this.edit ? this.$store.state.editAddress.buildingName: null; | ||||
|          this.address.distribution = this.edit ? this.$store.state.editAddress.distribution: null; | ||||
|          this.address.extra = this.edit ? this.$store.state.editAddress.extra: null; | ||||
|          this.address.writeNewAddress = this.edit; | ||||
|          this.address.writeNewPostalCode = this.edit; | ||||
|          this.address.newPostalCode = this.edit ? | ||||
|              { | ||||
|                  code: this.$store.state.editAddress.postcode !== undefined ? this.$store.state.editAddress.postcode.code : null, | ||||
|                  name: this.$store.state.editAddress.postcode !== undefined ? this.$store.state.editAddress.postcode.name : null | ||||
|              } : {}; | ||||
|          console.log('cities and addresses', this.address.loaded.cities, this.address.loaded.addresses); | ||||
|       } | ||||
|    } | ||||
|   | ||||
| @@ -40,7 +40,7 @@ export default { | ||||
|       update() { | ||||
|          console.log('update map with : ', this.address.addressMap.center) | ||||
|          marker.setLatLng(this.address.addressMap.center); | ||||
|          map.setView(this.address.addressMap.center, 12); | ||||
|          map.setView(this.address.addressMap.center, 15); | ||||
|       } | ||||
|    }, | ||||
|    mounted(){ | ||||
|   | ||||
| @@ -1,37 +1,56 @@ | ||||
| <template> | ||||
|    <h4>{{ $t('fill_an_address') }}</h4> | ||||
|    <div> | ||||
|       <h4>{{ $t('fill_an_address') }}</h4> | ||||
|       <input  | ||||
|       <label for="floor">{{ $t('floor') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="floor" | ||||
|          :placeholder="$t('floor')" | ||||
|          v-model="floor"/> | ||||
|       <input  | ||||
|       </div> | ||||
|    <div> | ||||
|       <label for="corridor">{{ $t('corridor') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="corridor" | ||||
|          :placeholder="$t('corridor')" | ||||
|          v-model="corridor"/> | ||||
|       <input  | ||||
|    </div> | ||||
|    <div> | ||||
|       <label for="steps">{{ $t('steps') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="steps" | ||||
|          :placeholder="$t('steps')" | ||||
|          v-model="steps"/> | ||||
|       <input  | ||||
|    </div> | ||||
|    <div> | ||||
|       <label for="flat">{{ $t('flat') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="flat" | ||||
|          :placeholder="$t('flat')" | ||||
|          v-model="flat"/> | ||||
|       <input  | ||||
|    </div> | ||||
|    <div> | ||||
|       <label for="buildingName">{{ $t('buildingName') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="buildingName" | ||||
|          :placeholder="$t('buildingName')" | ||||
|          v-model="buildingName"/> | ||||
|       <input  | ||||
|    </div> | ||||
|    <div> | ||||
|       <label for="extra">{{ $t('extra') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="extra" | ||||
|          :placeholder="$t('extra')" | ||||
|          v-model="extra"/> | ||||
|       <input  | ||||
|    </div> | ||||
|    <div> | ||||
|       <label for="distribution">{{ $t('distribution') }}</label> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="distribution" | ||||
|          :placeholder="$t('distribution')" | ||||
|   | ||||
| @@ -15,6 +15,18 @@ | ||||
|          :options="addresses"> | ||||
|       </VueMultiselect> | ||||
|    </div> | ||||
|    <div class="custom-address" v-if="writeNewAddress || writeNewPostalCode"> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="street" | ||||
|          :placeholder="$t('street')" | ||||
|          v-model="street"/> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="streetNumber" | ||||
|          :placeholder="$t('streetNumber')" | ||||
|          v-model="streetNumber"/> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| @@ -30,9 +42,31 @@ export default { | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
|       writeNewAddress() { | ||||
|          return this.address.writeNewAddress; | ||||
|       }, | ||||
|       writeNewPostalCode() { | ||||
|          return this.address.writeNewPostalCode; | ||||
|       }, | ||||
|       addresses() { | ||||
|          return this.address.loaded.addresses; | ||||
|       } | ||||
|       }, | ||||
|       street: { | ||||
|          set(value) { | ||||
|             this.address.street = value; | ||||
|          }, | ||||
|          get() { | ||||
|             return this.address.street; | ||||
|          } | ||||
|       }, | ||||
|       streetNumber: { | ||||
|          set(value) { | ||||
|             this.address.streetNumber = value; | ||||
|          }, | ||||
|          get() { | ||||
|             return this.address.streetNumber; | ||||
|          } | ||||
|       }, | ||||
|    }, | ||||
|    methods: { | ||||
|       transName(value) { | ||||
| @@ -40,14 +74,12 @@ export default { | ||||
|       }, | ||||
|       selectAddress(value) { | ||||
|          this.address.selected.address = value; | ||||
|          this.address.street = value.street; | ||||
|          this.address.streetNumber = value.streetNumber; | ||||
|          this.updateMapCenter(value.point); | ||||
|       }, | ||||
|       addAddress (newAddress) { | ||||
|          const address = { | ||||
|             street: newAddress | ||||
|          }; | ||||
|          this.value = address; | ||||
|          this.address.selected.address = address; | ||||
|       addAddress() { | ||||
|          this.address.writeNewAddress = true; | ||||
|       } | ||||
|    } | ||||
| }; | ||||
|   | ||||
| @@ -8,9 +8,25 @@ | ||||
|          label="value" | ||||
|          :custom-label="transName" | ||||
|          :placeholder="$t('select_city')" | ||||
|          :taggable="true" | ||||
|          :multiple="false" | ||||
|          @tag="addPostalCode" | ||||
|          :tagPlaceholder="$t('create_postal_code')" | ||||
|          :options="cities"> | ||||
|       </VueMultiselect> | ||||
|    </div> | ||||
|    <div class="custom-postcode" v-if="writeNewPostalCode"> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="name" | ||||
|          :placeholder="$t('postalCode_name')" | ||||
|          v-model="name"/> | ||||
|       <input | ||||
|          type="text" | ||||
|          name="code" | ||||
|          :placeholder="$t('postalCode_code')" | ||||
|          v-model="code"/> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| @@ -25,18 +41,42 @@ export default { | ||||
|          value: null | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
|       writeNewPostalCode() { | ||||
|          return this.address.writeNewPostalCode; | ||||
|       }, | ||||
|       cities() { | ||||
|          return this.address.loaded.cities; | ||||
|       }, | ||||
|       name: { | ||||
|          set(value) { | ||||
|             this.address.newPostalCode.name = value; | ||||
|          }, | ||||
|          get() { | ||||
|             return this.address.newPostalCode.name; | ||||
|          } | ||||
|       }, | ||||
|       code: { | ||||
|          set(value) { | ||||
|             this.address.newPostalCode.code= value; | ||||
|          }, | ||||
|          get() { | ||||
|             return this.address.newPostalCode.code; | ||||
|          } | ||||
|       }, | ||||
|    }, | ||||
|    methods: { | ||||
|       transName(value) { | ||||
|          return `${value.code}-${value.name}` | ||||
|       }, | ||||
|       selectCity(value) { | ||||
|          this.address.selected.city = value; | ||||
|          this.address.newPostalCode.name = value.name; | ||||
|          this.address.newPostalCode.code = value.code; | ||||
|          this.getReferenceAddresses(value); | ||||
|       }, | ||||
|    }, | ||||
|    computed: { | ||||
|       cities() { | ||||
|          return this.address.loaded.cities; | ||||
|       addPostalCode() { | ||||
|          this.address.writeNewPostalCode = true; | ||||
|       } | ||||
|    } | ||||
| }; | ||||
|   | ||||
| @@ -22,13 +22,18 @@ export default { | ||||
|    props: ['address', 'getCities'], | ||||
|    data() { | ||||
|       return { | ||||
|          value: this.address.loaded.countries.filter(c => c.countryCode === 'FR')[0] | ||||
|          edit: window.mode === 'edit', | ||||
|          defaultCountry: this.edit ? this.$store.state.editAddress.country.code : 'FR', | ||||
|          value: this.address.loaded.countries.filter(c => c.countryCode === this.defaultCountry)[0] | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       init() { | ||||
|          this.value = this.edit ? | ||||
|             this.address.loaded.countries.filter(c => c.countryCode === this.$store.state.editAddress.country.code)[0]: | ||||
|             this.address.loaded.countries.filter(c => c.countryCode === 'FR')[0] | ||||
|          if (this.value !== undefined) { | ||||
|             this.getCities(this.value); | ||||
|             this.selectCountry(this.value); | ||||
|          } | ||||
|       }, | ||||
|       transName ({ name }) { | ||||
|   | ||||
| @@ -0,0 +1,44 @@ | ||||
| <template> | ||||
|    <div v-if="address.text"> | ||||
|       {{ address.text }} | ||||
|    </div> | ||||
|    <div v-if="address.postcode"> | ||||
|       {{ address.postcode.name }} | ||||
|    </div> | ||||
|    <div v-if="address.country"> | ||||
|       {{ address.country.name.fr }} | ||||
|    </div> | ||||
|    <div v-if="address.floor"> | ||||
|       <span>{{ $t('floor') }}</span>: {{ address.floor }} | ||||
|    </div> | ||||
|    <div v-if="address.corridor"> | ||||
|       <span>{{ $t('corridor') }}</span>: {{ address.corridor }} | ||||
|    </div> | ||||
|    <div v-if="address.steps"> | ||||
|       <span>{{ $t('steps') }}</span>: {{ address.steps }} | ||||
|    </div> | ||||
|    <div v-if="address.flat"> | ||||
|       <span>{{ $t('flat') }}</span>: {{ address.flat }} | ||||
|    </div> | ||||
|    <div v-if="address.buildingName"> | ||||
|       <span>{{ $t('buildingName') }}</span>: {{ address.buildingName }} | ||||
|    </div> | ||||
|    <div v-if="address.extra"> | ||||
|       <span>{{ $t('extra') }}</span>: {{ address.extra }} | ||||
|    </div> | ||||
|    <div v-if="address.distribution"> | ||||
|       <span>{{ $t('distribution') }}</span>: {{ address.distribution }} | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| export default { | ||||
|    name: 'ShowAddress', | ||||
|    props: ['address'], | ||||
|    data() { | ||||
|       return { | ||||
|       } | ||||
|    }, | ||||
| }; | ||||
| </script> | ||||
| @@ -14,8 +14,20 @@ class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface | ||||
|     public function normalize($address, string $format = null, array $context = []) | ||||
|     { | ||||
|         $data['address_id'] = $address->getId(); | ||||
|         $data['text'] = $address->getStreet().', '.$address->getBuildingName(); | ||||
|         $data['text'] = $address->getStreet().', '.$address->getStreetNumber(); | ||||
|         $data['street'] = $address->getStreet(); | ||||
|         $data['streetNumber'] = $address->getStreetNumber(); | ||||
|         $data['postcode']['name'] = $address->getPostCode()->getName(); | ||||
|         $data['postcode']['code'] = $address->getPostCode()->getCode(); | ||||
|         $data['country']['name'] = $address->getPostCode()->getCountry()->getName(); | ||||
|         $data['country']['code'] = $address->getPostCode()->getCountry()->getCountryCode(); | ||||
|         $data['floor'] = $address->getFloor(); | ||||
|         $data['corridor'] = $address->getCorridor(); | ||||
|         $data['steps'] = $address->getSteps(); | ||||
|         $data['flat'] = $address->getBuildingName(); | ||||
|         $data['buildingName'] = $address->getFlat(); | ||||
|         $data['distribution'] = $address->getDistribution(); | ||||
|         $data['extra'] = $address->getExtra(); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| @@ -25,5 +37,5 @@ class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface | ||||
|         return $data instanceof Address; | ||||
|     } | ||||
|  | ||||
|      | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -17,6 +17,93 @@ components: | ||||
|           type: integer | ||||
|         name: | ||||
|           type: string | ||||
|     Address: | ||||
|       type: object | ||||
|       properties: | ||||
|         address_id: | ||||
|           type: integer | ||||
|         text: | ||||
|           type: string | ||||
|         postcode: | ||||
|           type: object | ||||
|           properties: | ||||
|             name: | ||||
|               type: string | ||||
|  | ||||
|     Country: | ||||
|       type: object | ||||
|       properties: | ||||
|         id: | ||||
|           type: integer | ||||
|         name: | ||||
|           type: object | ||||
|         countryCode: | ||||
|           type: string | ||||
|  | ||||
|     PostalCode: | ||||
|       type: object | ||||
|       properties: | ||||
|         id: | ||||
|           type: integer | ||||
|         name: | ||||
|           type: string | ||||
|         code: | ||||
|           type: string | ||||
|         country: | ||||
|           type: object | ||||
|           properties: | ||||
|             id: | ||||
|               type: integer | ||||
|             name: | ||||
|               type: object | ||||
|             countryCode: | ||||
|               type: string | ||||
|  | ||||
|     AddressReference: | ||||
|       type: object | ||||
|       properties: | ||||
|         id: | ||||
|           type: integer | ||||
|         refId: | ||||
|           type: string | ||||
|         street: | ||||
|           type: string | ||||
|         streetNumber: | ||||
|           type: string | ||||
|         postcode: | ||||
|           type: object | ||||
|           properties: | ||||
|             id: | ||||
|               type: integer | ||||
|             name: | ||||
|               type: string | ||||
|             code: | ||||
|               type: string | ||||
|             country: | ||||
|               type: object | ||||
|               properties: | ||||
|                 id: | ||||
|                   type: integer | ||||
|                 name: | ||||
|                   type: object | ||||
|                 countryCode: | ||||
|                   type: string | ||||
|         municipalityCode: | ||||
|           type: string | ||||
|         source: | ||||
|           type: string | ||||
|         point: | ||||
|           type: object | ||||
|           properties: | ||||
|             type: | ||||
|               type: string | ||||
|             coordinates: | ||||
|               type: array | ||||
|               items: | ||||
|                 type: number | ||||
|               minItems: 2 | ||||
|               maxItems: 2 | ||||
|  | ||||
|  | ||||
| paths: | ||||
|   /1.0/search.json: | ||||
| @@ -29,7 +116,7 @@ paths: | ||||
|       description: > | ||||
|         **Warning**: This is currently a stub (not really implemented | ||||
|  | ||||
|         The search is performed across multiple entities. The entities must be listed into  | ||||
|         The search is performed across multiple entities. The entities must be listed into | ||||
|         `type` parameters. | ||||
|  | ||||
|         The results are ordered by relevance, from the most to the lowest relevant. | ||||
| @@ -55,4 +142,286 @@ paths: | ||||
|       responses: | ||||
|         200: | ||||
|           description: "OK" | ||||
|   /1.0/main/address.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a list of all Chill addresses | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|     post: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: create a new address | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               type: object | ||||
|               properties: | ||||
|                 buildingName: | ||||
|                   type: string | ||||
|                 corridor: | ||||
|                   type: string | ||||
|                 distribution: | ||||
|                   type: string | ||||
|                 extra: | ||||
|                   type: string | ||||
|                 flat: | ||||
|                   type: string | ||||
|                 floor: | ||||
|                   type: string | ||||
|                 isNoAddress: | ||||
|                   type: boolean | ||||
|                 point: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: number | ||||
|                   minItems: 2 | ||||
|                   maxItems: 2 | ||||
|                 postcode: | ||||
|                   $ref: '#/components/schemas/PostalCode' | ||||
|                 steps: | ||||
|                   type: string | ||||
|                 street: | ||||
|                   type: string | ||||
|                 streetNumber: | ||||
|                   type: string | ||||
|       responses: | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|         404: | ||||
|           description: "Not found" | ||||
|         200: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|     patch: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: patch an address | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               type: object | ||||
|               properties: | ||||
|                 buildingName: | ||||
|                   type: string | ||||
|                 corridor: | ||||
|                   type: string | ||||
|                 distribution: | ||||
|                   type: string | ||||
|                 extra: | ||||
|                   type: string | ||||
|                 flat: | ||||
|                   type: string | ||||
|                 floor: | ||||
|                   type: string | ||||
|                 isNoAddress: | ||||
|                   type: boolean | ||||
|                 point: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: number | ||||
|                   minItems: 2 | ||||
|                   maxItems: 2 | ||||
|                 postcode: | ||||
|                   $ref: '#/components/schemas/PostalCode' | ||||
|                 steps: | ||||
|                   type: string | ||||
|                 street: | ||||
|                   type: string | ||||
|                 streetNumber: | ||||
|                   type: string | ||||
|                 validFrom: | ||||
|                   type: string | ||||
|                 validTo: | ||||
|                   type: string | ||||
|       responses: | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|         404: | ||||
|           description: "Not found" | ||||
|         200: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|  | ||||
|   /1.0/main/address/{id}.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return an address by id | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The address id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/Address' | ||||
|         404: | ||||
|           description: "not found" | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|  | ||||
|   /1.0/main/address-reference.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a list of all reference addresses | ||||
|       parameters: | ||||
|         - in: query | ||||
|           name: postal_code | ||||
|           required: false | ||||
|           schema: | ||||
|             type: integer | ||||
|           description: The id of a postal code to filter the reference addresses | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|   /1.0/main/address-reference/{id}.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a reference address by id | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The reference address id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/AddressReference' | ||||
|         404: | ||||
|           description: "not found" | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|  | ||||
|   /1.0/main/postal-code.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a list of all postal-code | ||||
|       parameters: | ||||
|         - in: query | ||||
|           name: country | ||||
|           required: false | ||||
|           schema: | ||||
|             type: integer | ||||
|           description: The id of a country to filter the postal code | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|     post: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: create a new PostalCode | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               type: object | ||||
|               properties: | ||||
|                 name: | ||||
|                   type: string | ||||
|                 code: | ||||
|                   type: string | ||||
|                 country: | ||||
|                   $ref: '#/components/schemas/Country' | ||||
|       responses: | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|         404: | ||||
|           description: "Not found" | ||||
|         200: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|  | ||||
|   /1.0/main/postal-code/{id}.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a postal code by id | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The postal code id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/PostalCode' | ||||
|         404: | ||||
|           description: "not found" | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|  | ||||
|   /1.0/main/country.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a list of all countries | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|   /1.0/main/country/{id}.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - address | ||||
|       summary: Return a country by id | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The country id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/Country' | ||||
|         404: | ||||
|           description: "not found" | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|   | ||||
| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\Migrations\Main; | ||||
|  | ||||
| use Doctrine\DBAL\Schema\Schema; | ||||
| use Doctrine\Migrations\AbstractMigration; | ||||
|  | ||||
| /** | ||||
|  * Auto-generated Migration: Please modify to your needs! | ||||
|  */ | ||||
| final class Version20210616134328 extends AbstractMigration | ||||
| { | ||||
|     public function getDescription(): string | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     public function up(Schema $schema): void | ||||
|     { | ||||
|         $this->addSql('ALTER TABLE chill_main_postal_code ADD origin INT DEFAULT NULL'); | ||||
|     } | ||||
|  | ||||
|     public function down(Schema $schema): void | ||||
|     { | ||||
|         $this->addSql('ALTER TABLE chill_main_postal_code DROP origin'); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\PersonBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Chill\MainBundle\Entity\Address; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
|  | ||||
| class HouseholdApiController extends ApiController | ||||
| { | ||||
|  | ||||
|     public function householdAddressApi($id, Request $request, string $_format): Response | ||||
|     { | ||||
|         return $this->addRemoveSomething('address', $id, $request, $_format, 'address', Address::class, [ 'groups' => [ 'read' ] ]); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| namespace Chill\PersonBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\Entity\Address; | ||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -84,6 +85,16 @@ class HouseholdController extends AbstractController | ||||
|     public function addresses(Request $request, Household $household) | ||||
|     { | ||||
|         // TODO ACL | ||||
|  | ||||
|         //TODO put these lines into a validator constraint on household->getAddress | ||||
|         $addresses = $household->getAddresses(); | ||||
|         $cond = True; | ||||
|         for ($i=0; $i < count($addresses) - 1; $i++) { | ||||
|             if ($addresses[$i]->getValidFrom() != $addresses[$i + 1]->getValidTo()) { | ||||
|                 $cond = False; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $this->render('@ChillPerson/Household/addresses.html.twig', | ||||
|             [ | ||||
|                 'household' => $household | ||||
| @@ -91,6 +102,7 @@ class HouseholdController extends AbstractController | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @Route( | ||||
|      *      "/{household_id}/address/move", | ||||
| @@ -102,10 +114,33 @@ class HouseholdController extends AbstractController | ||||
|     public function addressMove(Request $request, Household $household) | ||||
|     { | ||||
|         // TODO ACL | ||||
|  | ||||
|         return $this->render('@ChillPerson/Household/address_move.html.twig', | ||||
|             [ | ||||
|                 'household' => $household | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @Route( | ||||
|      *      "/{household_id}/address/edit", | ||||
|      *      name="chill_person_household_address_edit", | ||||
|      *      methods={"GET", "HEAD", "POST"} | ||||
|      *  ) | ||||
|      *  @ParamConverter("household", options={"id" = "household_id"}) | ||||
|      */ | ||||
|     public function addressEdit(Request $request, Household $household) | ||||
|     { | ||||
|         // TODO ACL | ||||
|         //$address = $this->findAddressById($household, $address_id); //TODO | ||||
|  | ||||
|  | ||||
|         return $this->render('@ChillPerson/Household/address_edit.html.twig', | ||||
|             [ | ||||
|                 'household' => $household, | ||||
|                 //'address' => $address, | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -45,7 +45,7 @@ class PersonAddressController extends AbstractController | ||||
|      * @var ValidatorInterface | ||||
|      */ | ||||
|     protected $validator; | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * PersonAddressController constructor. | ||||
|      * | ||||
| @@ -55,7 +55,7 @@ class PersonAddressController extends AbstractController | ||||
|     { | ||||
|         $this->validator = $validator; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     public function listAction($person_id) | ||||
|     { | ||||
|         $person = $this->getDoctrine()->getManager() | ||||
|   | ||||
| @@ -22,7 +22,8 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; | ||||
| use Symfony\Component\Security\Core\Role\Role; | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Chill\MainBundle\Entity\Address; | ||||
|  | ||||
| class PersonApiController extends ApiController | ||||
| { | ||||
| @@ -35,7 +36,7 @@ class PersonApiController extends ApiController | ||||
|     { | ||||
|         $this->authorizationHelper = $authorizationHelper; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     protected function createEntity(string $action, Request $request): object | ||||
|     { | ||||
|         $person = parent::createEntity($action, $request); | ||||
| @@ -47,4 +48,10 @@ class PersonApiController extends ApiController | ||||
|  | ||||
|         return $person; | ||||
|     } | ||||
|  | ||||
|     public function personAddressApi($id, Request $request, string $_format): Response | ||||
|     { | ||||
|         return $this->addRemoveSomething('address', $id, $request, $_format, 'address', Address::class, [ 'groups' => [ 'read' ] ]); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -201,7 +201,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|            'workflows' => [ | ||||
|                 'accompanying_period_lifecycle' => [ | ||||
|                     'type' =>  'state_machine', | ||||
|                     'audit_trail' => [  | ||||
|                     'audit_trail' => [ | ||||
|                         'enabled' =>  true | ||||
|                     ], | ||||
|                     'marking_store' => [ | ||||
| @@ -354,15 +354,15 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|                     'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseApiController::class, | ||||
|                     'actions' => [ | ||||
|                         '_entity' => [ | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_PATCH => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_PUT => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                             ], | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true,  | ||||
|                                 Request::METHOD_PUT => true,  | ||||
|                                 Request::METHOD_PATCH => true,  | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_PUT => true, | ||||
|                                 Request::METHOD_PATCH => true, | ||||
|                             ] | ||||
|                         ], | ||||
|                         'participation' => [ | ||||
| @@ -379,61 +379,61 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|                         ], | ||||
|                         'resource' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE | ||||
|                             ] | ||||
|                         ], | ||||
|                         'comment' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE | ||||
|                             ] | ||||
|                         ], | ||||
|                         'requestor' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE | ||||
|                             ] | ||||
|                         ], | ||||
|                         'scope' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE | ||||
|                             ] | ||||
|                         ], | ||||
|                         'socialissue' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'controller_action' => 'socialIssueApi', | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                                 Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE | ||||
|                             ] | ||||
| @@ -441,11 +441,11 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|  | ||||
|                         'confirm' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true,  | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'roles' => [  | ||||
|                             'roles' => [ | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, | ||||
|                             ] | ||||
|                         ], | ||||
| @@ -510,8 +510,48 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|                                 Request::METHOD_HEAD => \Chill\PersonBundle\Security\Authorization\PersonVoter::SEE, | ||||
|                                 Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\PersonVoter::CREATE, | ||||
|  | ||||
|                             ], | ||||
|                         ], | ||||
|                         'address' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'controller_action' => 'personAddressApi' | ||||
|                         ], | ||||
|                     ] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'class' => \Chill\PersonBundle\Entity\Household\Household::class, | ||||
|                     'controller' => \Chill\PersonBundle\Controller\HouseholdApiController::class, | ||||
|                     'name' => 'household', | ||||
|                     'base_path' => '/api/1.0/person/household', | ||||
|                     'base_role' => 'ROLE_USER', | ||||
|                     'actions' => [ | ||||
|                         '_index' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                             ], | ||||
|                         ], | ||||
|                         '_entity' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                                 Request::METHOD_POST=> true, | ||||
|                             ] | ||||
|                         ], | ||||
|                         'address' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_POST => true, | ||||
|                                 Request::METHOD_DELETE => true, | ||||
|                                 Request::METHOD_GET => false, | ||||
|                                 Request::METHOD_HEAD => false, | ||||
|                             ], | ||||
|                             'controller_action' => 'householdAddressApi' | ||||
|                         ], | ||||
|                     ] | ||||
|                 ], | ||||
|                 [ | ||||
|   | ||||
| @@ -7,6 +7,8 @@ use Doctrine\ORM\Mapping as ORM; | ||||
| use Doctrine\Common\Collections\Collection; | ||||
| use Doctrine\Common\Collections\Criteria; | ||||
| use Symfony\Component\Serializer\Annotation as Serializer; | ||||
| use Symfony\Component\Validator\Constraints as Assert; | ||||
| use Symfony\Component\Validator\Context\ExecutionContextInterface; | ||||
| use Chill\MainBundle\Entity\Address; | ||||
| use Chill\PersonBundle\Entity\Household\HouseholdMember; | ||||
|  | ||||
| @@ -25,7 +27,7 @@ class Household | ||||
|      * @ORM\Id | ||||
|      * @ORM\GeneratedValue | ||||
|      * @ORM\Column(type="integer") | ||||
|      * @Serializer\Groups({"read"}) | ||||
|      * @Serializer\Groups({"write"}) | ||||
|      */ | ||||
|     private ?int $id = null; | ||||
|  | ||||
| @@ -37,6 +39,7 @@ class Household | ||||
|      *     cascade={"persist", "remove", "merge", "detach"}) | ||||
|      * @ORM\JoinTable(name="chill_person_household_to_addresses") | ||||
|      * @ORM\OrderBy({"validFrom" = "DESC"}) | ||||
|      * @Serializer\Groups({"write"}) | ||||
|      */ | ||||
|     private Collection $addresses; | ||||
|  | ||||
| @@ -45,7 +48,7 @@ class Household | ||||
|      *      targetEntity=HouseholdMember::class, | ||||
|      *      mappedBy="household" | ||||
|      *  ) | ||||
|      * @Serializer\Groups({"read"}) | ||||
|      * @Serializer\Groups({"write"}) | ||||
|      */ | ||||
|     private Collection $members; | ||||
|  | ||||
| @@ -68,6 +71,11 @@ class Household | ||||
|     { | ||||
|         $this->addresses[] = $address; | ||||
|  | ||||
|         foreach ($this->getAddresses() as $a) { | ||||
|             if ($a->getValidFrom() < $address->getValidFrom() && $a->getValidTo() === NULL) { | ||||
|                 $a->setValidTo($address->getValidFrom()); | ||||
|             } | ||||
|         } | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
| @@ -83,6 +91,7 @@ class Household | ||||
|      * By default, the addresses are ordered by date, descending (the most | ||||
|      * recent first) | ||||
|      * | ||||
|      * @Assert\Callback(methods={"validate"}) | ||||
|      * @return \Chill\MainBundle\Entity\Address[] | ||||
|      */ | ||||
|     public function getAddresses() | ||||
| @@ -192,4 +201,20 @@ class Household | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function validate(ExecutionContextInterface $context, $payload) | ||||
|     { | ||||
|         $addresses = $this->getAddresses(); | ||||
|         $cond = True; | ||||
|         for ($i=0; $i < count($addresses) - 1; $i++) { | ||||
|             if ($addresses[$i]->getValidFrom() != $addresses[$i + 1]->getValidTo()) { | ||||
|                 $cond = False; | ||||
|                 $context->buildViolation('The address are not sequentials. The validFrom date of one address should be equal to the validTo date of the previous address.') | ||||
|                     ->atPath('addresses') | ||||
|                     ->addViolation(); | ||||
|             } | ||||
|         } | ||||
|         dump($cond); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -86,3 +86,83 @@ div.person-view { | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  *  HOUSEHOLD | ||||
|  */ | ||||
|  | ||||
|  | ||||
| div.household__address, div.person__address { | ||||
|     div.row { | ||||
|         height: 100px; | ||||
|         width: 100%; | ||||
|         position: relative; | ||||
|         & > div { | ||||
|             position: absolute; | ||||
|             display: table; | ||||
|             height: 100%; | ||||
|             border: 1px dotted #c3c3c3; | ||||
|         } | ||||
|         div.household__address--date, div.person__address--date { | ||||
|             width: 30%; | ||||
|             background-color: #c3c3c3; | ||||
|             height: 100%; | ||||
|             div.cell { | ||||
|                 box-sizing: border-box; | ||||
|                 position: relative; | ||||
|                 height: 100%; | ||||
|                 width: 100%; | ||||
|                 margin-left: 50%; | ||||
|                 div.pill { | ||||
|                     position: absolute; | ||||
|                     box-sizing: border-box; | ||||
|                     width: 120px; | ||||
|                     height: 40px; | ||||
|                     bottom: -20px; | ||||
|                     background-color: white; | ||||
|                     padding: 10px; | ||||
|                     border-radius: 30px; | ||||
|                     left: -60px; | ||||
|                     text-align: center; | ||||
|                     z-index: 10; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         div.household__address--content, div.person__address--content { | ||||
|             width: 70%; | ||||
|             left: 30%; | ||||
|             text-align: left; | ||||
|             background-color: #ececec; | ||||
|             border: 1px solid #888; | ||||
|             div.cell { | ||||
|                 display: table-cell; | ||||
|                 padding: 5px 30px; | ||||
|                 vertical-align: middle; | ||||
|                 & > div { | ||||
|                     display: flex; | ||||
|                     justify-content: space-between; | ||||
|                 } | ||||
|                 i.dot::before, i.dot::after { | ||||
|                     position: absolute; | ||||
|                     width: 20px; | ||||
|                     height: 20px; | ||||
|                     content: ''; | ||||
|                     border: 0; | ||||
|                     background-color: white; | ||||
|                     border-radius: 50%; | ||||
|                     border: 5px solid #c3c3c3; | ||||
|                     z-index: 10; | ||||
|                     left: -15px; | ||||
|                     bottom: -15px; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| div.household__address-move { | ||||
|     div.household__address-move__create { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,119 @@ | ||||
| <template> | ||||
|    <div class='household__address-move'> | ||||
|       <div class='household__address-move__create'> | ||||
|          <div> | ||||
|             <h2>{{ $t('create_a_new_address') }}</h2> | ||||
|             <add-address | ||||
|                @addNewAddress="addNewAddress"> | ||||
|             </add-address> | ||||
|          </div> | ||||
|          <div> | ||||
|             <show-address | ||||
|                v-if="newAddress" | ||||
|                v-bind:address="newAddress"> | ||||
|             </show-address> | ||||
|          </div> | ||||
|       </div> | ||||
|       <div class='household__address-move__valid'> | ||||
|          <h2>{{ $t('move_date') }}</h2> | ||||
|          <input | ||||
|             type="date" | ||||
|             name="validFrom" | ||||
|             :placeholder="$t('validFrom')" | ||||
|             v-model="validFrom"/> | ||||
|          <div v-if="errors.length > 0"> | ||||
|             {{ errors }} | ||||
|          </div> | ||||
|       </div> | ||||
|       <div> | ||||
|          <ul class="record_actions sticky-form-buttons"> | ||||
|             <li class="cancel"> | ||||
|                <a :href=backUrl class="sc-button bt-cancel">{{ $t('back_to_the_list') }}</a> | ||||
|             </li> | ||||
|             <li> | ||||
|                <button type="submit" class="sc-button bt-update centered" @click="addToHousehold"> | ||||
|                   {{ $t('add_an_address_to_household') }} | ||||
|                </button> | ||||
|             </li> | ||||
|          </ul> | ||||
|       </div> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| import AddAddress from 'ChillMainAssets/vuejs/_components/AddAddress.vue'; | ||||
| import ShowAddress from 'ChillMainAssets/vuejs/_components/ShowAddress.vue'; | ||||
|  | ||||
| export default { | ||||
|    name: 'App', | ||||
|    components: { | ||||
|       AddAddress, | ||||
|       ShowAddress | ||||
|    }, | ||||
|    data() { | ||||
|       return { | ||||
|          edit: window.mode === 'edit', | ||||
|          householdId: window.householdId, | ||||
|          backUrl: `/fr/person/household/${householdId}/addresses`, //TODO better way to pass this | ||||
|          validFrom: new Date().toISOString().split('T')[0] | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
|       newAddress() { | ||||
|          return this.$store.state.newAddress; | ||||
|       }, | ||||
|       errors() { | ||||
|          return this.$store.state.errorMsg; | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       addNewAddress({ address, modal }) { | ||||
|          console.log('@@@ CLICK button addNewAdress', address); | ||||
|  | ||||
|          let createdAddress = { | ||||
|             'isNoAddress': address.isNoAddress, | ||||
|             'street': address.isNoAddress ? '' : address.street, | ||||
|             'streetNumber': address.isNoAddress ? '' : address.streetNumber, | ||||
|             'postcode': {'id': address.selected.city.id}, | ||||
|             'floor': address.floor, | ||||
|             'corridor': address.corridor, | ||||
|             'steps': address.steps, | ||||
|             'flat': address.flat, | ||||
|             'buildingName': address.buildingName, | ||||
|             'distribution': address.distribution, | ||||
|             'extra': address.extra | ||||
|          }; | ||||
|  | ||||
|          if (address.selected.address.point !== undefined){ | ||||
|             createdAddress = Object.assign(createdAddress, { | ||||
|                'point': address.selected.address.point.coordinates | ||||
|             }); | ||||
|          } | ||||
|  | ||||
|          if(address.writeNewPostalCode){ | ||||
|             let newPostalCode = address.newPostalCode; | ||||
|             newPostalCode = Object.assign(newPostalCode, { | ||||
|                 'country': {'id': address.selected.country.id }, | ||||
|             }); | ||||
|             createdAddress = Object.assign(createdAddress, { | ||||
|                'newPostalCode': newPostalCode | ||||
|             }); | ||||
|          } | ||||
|  | ||||
|          this.$store.dispatch('addAddress', createdAddress); | ||||
|  | ||||
|          modal.showModal = false; | ||||
|       }, | ||||
|       addToHousehold() { | ||||
|         this.$store.dispatch('addDateToAddressAndAddressToHousehold', { | ||||
|            householdId: this.householdId, | ||||
|            addressId: this.$store.state.newAddress.address_id, | ||||
|            body: { validFrom: {datetime: `${this.validFrom}T00:00:00+0100`}} | ||||
|         }) | ||||
|       } | ||||
|    } | ||||
| }; | ||||
|  | ||||
| </script> | ||||
|  | ||||
| @@ -0,0 +1,23 @@ | ||||
| /* | ||||
| * Endpoint household | ||||
| * method POST, post Household instance | ||||
| * | ||||
| *  @id     integer - id of household | ||||
| *  @body   Object - dictionary with changes to post | ||||
| */ | ||||
| export const postAddressToHousehold = (householdId, addressId) => { | ||||
|    const body = { | ||||
|       'id': addressId | ||||
|    }; | ||||
|    const url = `/api/1.0/person/household/${householdId}/address.json` | ||||
|    return fetch(url, { | ||||
|          method: 'POST', | ||||
|          headers: {'Content-Type': 'application/json;charset=utf-8'}, | ||||
|          body: JSON.stringify(body) | ||||
|       }) | ||||
|       .then(response => { | ||||
|          if (response.ok) { return response.json(); } | ||||
|          throw Error('Error with request resource response'); | ||||
|       }); | ||||
| }; | ||||
|  | ||||
| @@ -0,0 +1,47 @@ | ||||
| <template> | ||||
|    <div class="container"> | ||||
|       <VueMultiselect | ||||
|          v-model="value" | ||||
|          @select="selectAddress" | ||||
|          name="field" | ||||
|          track-by="id" | ||||
|          label="value" | ||||
|          :custom-label="transName" | ||||
|          :multiple="false" | ||||
|          :placeholder="$t('select_address')" | ||||
|          :options="addresses"> | ||||
|       </VueMultiselect> | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import VueMultiselect from 'vue-multiselect'; | ||||
|  | ||||
| export default { | ||||
|    name: 'SelectHouseholdAddress', | ||||
|    components: { VueMultiselect }, | ||||
|    props: ['address'], | ||||
|    data() { | ||||
|       return { | ||||
|          value: null | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
|       addresses() { | ||||
|          return this.address.loaded.addresses; | ||||
|       } | ||||
|    }, | ||||
|    methods: { | ||||
|       transName(value) { | ||||
|          return `${value.text} ${value.postcode.name}` | ||||
|       }, | ||||
|       selectAddress(value) { | ||||
|          this.address.selected.address = value; | ||||
|       } | ||||
|    } | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style src="vue-multiselect/dist/vue-multiselect.css"></style> | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,25 @@ | ||||
| import { createApp } from 'vue' | ||||
| import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n' | ||||
| import { appMessages } from './js/i18n' | ||||
| import { store } from './store' | ||||
|  | ||||
| import App from './App.vue'; | ||||
|  | ||||
| const root = window.vueRootComponent; | ||||
|  | ||||
| /* | ||||
| *  Load all App component, for Household edition page | ||||
| */ | ||||
|  | ||||
| const i18n = _createI18n(appMessages); | ||||
|  | ||||
| const app = createApp({ | ||||
|    template: `<app></app>`, | ||||
| }) | ||||
| .use(store) | ||||
| .use(i18n) | ||||
| .component('app', App) | ||||
| .mount('#household-address'); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,18 @@ | ||||
| import { addressMessages } from 'ChillMainAssets/vuejs/Address/js/i18n' | ||||
|  | ||||
| const appMessages = { | ||||
|    fr: { | ||||
|       select_a_existing_address: 'Sélectionner une adresse existante', | ||||
|       create_a_new_address: 'Créer une nouvelle adresse', | ||||
|       add_an_address_to_household: 'Déménager le ménage', | ||||
|       validFrom: 'Date du déménagement', | ||||
|       move_date: 'Date du déménagement', | ||||
|       back_to_the_list: 'Retour à la liste' | ||||
|    } | ||||
| }; | ||||
|  | ||||
| Object.assign(appMessages.fr, addressMessages.fr); | ||||
|  | ||||
| export { | ||||
|    appMessages | ||||
| }; | ||||
| @@ -0,0 +1,90 @@ | ||||
| import 'es6-promise/auto'; | ||||
| import { createStore } from 'vuex'; | ||||
|  | ||||
| import { postAddress, postPostalCode, patchAddress } from 'ChillMainAssets/vuejs/_api/AddAddress'; | ||||
| import { postAddressToHousehold } from '../api'; | ||||
|  | ||||
| const debug = process.env.NODE_ENV !== 'production'; | ||||
|  | ||||
| const store = createStore({ | ||||
|    strict: debug, | ||||
|    state: { | ||||
|       newAddress: {}, | ||||
|       household: {}, | ||||
|       validFrom: {}, | ||||
|       errorMsg: [] | ||||
|    }, | ||||
|    getters: { | ||||
|    }, | ||||
|    mutations: { | ||||
|       catchError(state, error) { | ||||
|          state.errorMsg.push(error); | ||||
|       }, | ||||
|       addAddress(state, address) { | ||||
|          console.log('@M addAddress address', address); | ||||
|          state.newAddress = address; | ||||
|       }, | ||||
|       addAddressToHousehold(state, household) { | ||||
|          console.log('@M addAddressToHousehold household', household); | ||||
|          state.household = household; | ||||
|       }, | ||||
|       addDateToAddress(state, validFrom) { | ||||
|          console.log('@M addDateToAddress address.validFrom', validFrom); | ||||
|          state.validFrom = validFrom; | ||||
|       } | ||||
|    }, | ||||
|    actions: { | ||||
|       addAddress({ commit }, payload) { | ||||
|          console.log('@A addAddress payload', payload); | ||||
|  | ||||
|          if('newPostalCode' in payload){ | ||||
|             postPostalCode(payload.newPostalCode) | ||||
|                .then(postalCode => { | ||||
|                   let body = payload; | ||||
|                   body.postcode = {'id': postalCode.id }, | ||||
|                   postAddress(body) | ||||
|                      .then(address => new Promise((resolve, reject) => { | ||||
|                         commit('addAddress', address); | ||||
|                         resolve(); | ||||
|                      })) | ||||
|                      .catch((error) => { | ||||
|                         commit('catchError', error); | ||||
|                      }); | ||||
|                }) | ||||
|  | ||||
|          } else { | ||||
|             postAddress(payload) | ||||
|                .then(address => new Promise((resolve, reject) => { | ||||
|                   commit('addAddress', address); | ||||
|                   resolve(); | ||||
|                })) | ||||
|                .catch((error) => { | ||||
|                   commit('catchError', error); | ||||
|                }); | ||||
|          } | ||||
|       }, | ||||
|       addDateToAddressAndAddressToHousehold({ commit }, payload) { | ||||
|          console.log('@A addDateToAddressAndAddressToHousehold payload', payload); | ||||
|  | ||||
|          patchAddress(payload.addressId, payload.body) | ||||
|             .then(address => new Promise((resolve, reject) => { | ||||
|                commit('addDateToAddress', address.validFrom); | ||||
|                resolve(); | ||||
|             }).then( | ||||
|                postAddressToHousehold(payload.householdId, payload.addressId) | ||||
|                   .then(household => new Promise((resolve, reject) => { | ||||
|                      commit('addAddressToHousehold', household); | ||||
|                      resolve(); | ||||
|                })) | ||||
|                .catch((error) => { | ||||
|                   commit('catchError', error); | ||||
|                }) | ||||
|             )) | ||||
|             .catch((error) => { | ||||
|                commit('catchError', error); | ||||
|             }); | ||||
|       }, | ||||
|    } | ||||
| }); | ||||
|  | ||||
| export { store }; | ||||
| @@ -18,31 +18,27 @@ | ||||
|  | ||||
| {% set activeRouteKey = '' %} | ||||
|  | ||||
| {% block title 'Update address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) %} | ||||
| {% block title 'Modify address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) %} | ||||
|  | ||||
| {% block personcontent %} | ||||
|  | ||||
|     <h1>{{ 'Update address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1> | ||||
|     {% block content %} | ||||
|         <h1>{{ block('title') }}</h1> | ||||
|         <div id="address"></div> | ||||
|     {% endblock %} | ||||
|  | ||||
|     {{ form_start(form) }} | ||||
|     {% block stylesheets %} | ||||
|         <link href="{{ asset('build/address.css') }}" type="text/css" rel="stylesheet" /> | ||||
|     {% endblock %} | ||||
|  | ||||
|     {{ form_row(form.isNoAddress) }} | ||||
|     {{ form_row(form.street) }} | ||||
|     {{ form_row(form.streetNumber) }} | ||||
|     {{ form_row(form.postCode) }} | ||||
|     {{ form_row(form.validFrom) }} | ||||
|  | ||||
|     <ul class="record_actions sticky-form-buttons"> | ||||
|         <li class="cancel"> | ||||
|             <a href="{{ path('chill_person_address_list', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel"> | ||||
|                     {{ 'Back to the list'|trans }} | ||||
|                 </a> | ||||
|         </li> | ||||
|         <li> | ||||
|             {{ form_row(form.submit, { 'attr' : { 'class': 'sc-button bt-save' }, 'label': 'Save' } ) }} | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|     {{ form_end(form) }} | ||||
|     {% block js %} | ||||
|         <script type="text/javascript"> | ||||
|             window.personId = {{ person.id|e('js') }}; | ||||
|             window.addressId = {{ address.id|e('js') }}; | ||||
|             window.mode = 'edit'; | ||||
|             window.vueRootComponent = 'app'; | ||||
|         </script> | ||||
|         {{ encore_entry_script_tags('address') }} | ||||
|     {% endblock %} | ||||
|  | ||||
| {% endblock personcontent %} | ||||
|   | ||||
| @@ -26,64 +26,76 @@ | ||||
|  | ||||
|     <h1>{{ 'Addresses\'history for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1> | ||||
|  | ||||
|     <table class="records_list"> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>{{ 'Valid from'|trans }}</th> | ||||
|                 <th>{{ 'Address'|trans }}</th> | ||||
|                 <th> </th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|             {% if person.addresses|length == 0 %} | ||||
|             <tr> | ||||
|                 <td colspan="3"> | ||||
|                     <span class="chill-no-data-statement">{{ 'No address given'|trans }}</span> | ||||
|                     <a href="{{ path('chill_person_address_new', { 'person_id' : person.id } ) }}"> | ||||
|     <div class="person__address"> | ||||
|  | ||||
|         <div class="row"> | ||||
|             <div class="person__address--date"></div> | ||||
|             <div class="person__address--content"> | ||||
|                 <div class="cell"> | ||||
|                     <div> | ||||
|                         {% if person.addresses|length == 0 %} | ||||
|                         <span class="chill-no-data-statement">{{ 'No address given'|trans }}</span> | ||||
|                         {% endif %} | ||||
|                         <a class="sc-button bt-create" | ||||
|                         href="{{ path('chill_person_address_new', { 'person_id' : person.id } ) }}"> | ||||
|                         {{ 'Add an address'|trans }} | ||||
|                     </a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             {% else %} | ||||
|             {% for address in person.addresses %} | ||||
|             <tr> | ||||
|                 <td><strong>{{ 'Since %date%'|trans( { '%date%' : address.validFrom|format_date('long') } ) }}</strong></td> | ||||
|                         </a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|                 <td> | ||||
|                 {{ address_macros._render(address, { 'with_valid_from' : false, 'has_no_address': true } ) }} | ||||
|                 </td> | ||||
|         {% for address in person.addresses %} | ||||
|         <div class="row"> | ||||
|             <div class="person__address--date"> | ||||
|                 <div class="cell"> | ||||
|                     <div class="pill"> | ||||
|                     {% if address.validFrom is not empty %} | ||||
|                     {{ address.validFrom|format_date('long') }} | ||||
|                     {% endif %} | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="person__address--content"> | ||||
|                 <div class="cell"> | ||||
|                     <i class="dot"></i> | ||||
|                     <div> | ||||
|                         {% if address.isNoAddress == true %} | ||||
|                         <div class="chill_address_is_noaddress">{{ 'address.consider homeless'|trans }}</div> | ||||
|                         {% else %} | ||||
|                         <div> | ||||
|                             {% if address.street is not empty %} | ||||
|                             <div class="street"> | ||||
|                                 <i class="fa fa-fw fa-map-marker"></i> | ||||
|                                 <span class="streetNumber">{{ address.street }}</span> | ||||
|                                 {% if address.streetNumber is not empty %} | ||||
|                                     <span class="streetNumber">, {{ address.streetNumber }}</span> | ||||
|                                 {% endif %} | ||||
|                             </div> | ||||
|                             {% endif %} | ||||
|                             {% if address.postCode is not empty %} | ||||
|                             <div class="postCode"> | ||||
|                                 <span>{{ address.postCode.code }}</span> <span>{{ address.postCode.name }}</span> | ||||
|                                 <span class="country">({{ address.postCode.country.name|localize_translatable_string }})</span> | ||||
|                             </div> | ||||
|                             {% endif %} | ||||
|                         </div> | ||||
|                         {% endif %} | ||||
|                         <a href="{{ path('chill_person_address_edit', { 'person_id': person.id, 'address_id' : address.id } ) }}" class="sc-button bt-edit"></a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         {% endfor %} | ||||
|     </div> | ||||
|  | ||||
|                 <td> | ||||
|                     <ul class="record_actions"> | ||||
|                         <li> | ||||
|                             <a href="{{ path('chill_person_address_edit', { 'person_id': person.id, 'address_id' : address.id } ) }}" class="sc-button bt-edit"></a> | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                 </td> | ||||
|             </tr> | ||||
|     <ul class="record_actions"> | ||||
|         <li class="cancel"> | ||||
|             <a href="{{ path('chill_person_view', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel"> | ||||
|                     {{ 'Back to the person details'|trans }} | ||||
|                 </a> | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|             {% endfor %} | ||||
|             {% endif %} | ||||
|         </tbody> | ||||
|     </table> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|         <ul class="record_actions"> | ||||
|             <li class="cancel"> | ||||
|                 <a href="{{ path('chill_person_view', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel"> | ||||
|                         {{ 'Back to the person details'|trans }} | ||||
|                     </a> | ||||
|             </li> | ||||
|             <li> | ||||
|  | ||||
|                 <a href="{{ path('chill_person_address_new', { 'person_id' : person.id } ) }}" class="sc-button bt-create"> | ||||
|                         {{ 'Add an address'|trans }} | ||||
|                     </a> | ||||
|             </li> | ||||
|         </ul> | ||||
|  | ||||
| {% endblock personcontent %} | ||||
|   | ||||
| @@ -22,36 +22,6 @@ | ||||
|  | ||||
| {% block personcontent %} | ||||
|  | ||||
|     <h1>{{ 'New address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1> | ||||
|  | ||||
|     {{ form_start(form) }} | ||||
|  | ||||
|     {{ form_row(form.isNoAddress) }} | ||||
|     {{ form_row(form.street) }} | ||||
|     {{ form_errors(form.street) }} | ||||
|     {{ form_row(form.streetNumber) }} | ||||
|     {{ form_errors(form.streetNumber) }} | ||||
|     {{ form_row(form.postCode) }} | ||||
|     {{ form_errors(form.postCode) }} | ||||
|     {{ form_row(form.validFrom) }} | ||||
|     {{ form_errors(form.validFrom) }} | ||||
|  | ||||
|     <ul class="record_actions sticky-form-buttons"> | ||||
|         <li class="cancel"> | ||||
|             <a href="{{ path('chill_person_address_list', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel"> | ||||
|                     {{ 'Back to the list'|trans }} | ||||
|                 </a> | ||||
|         </li> | ||||
|         <li> | ||||
|             {{ form_row(form.submit, { 'attr' : { 'class': 'sc-button bt-create'  }, 'label': 'Create' } ) }} | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|     {{ form_end(form) }} | ||||
|  | ||||
|  | ||||
|     NEW FORM | ||||
|  | ||||
|     {% block content %} | ||||
|         <h1>{{ block('title') }}</h1> | ||||
|         <div id="address"></div> | ||||
| @@ -62,6 +32,11 @@ | ||||
|     {% endblock %} | ||||
|  | ||||
|     {% block js %} | ||||
|         <script type="text/javascript"> | ||||
|             window.personId = {{ person.id|e('js') }}; | ||||
|             window.mode = 'new'; | ||||
|             window.vueRootComponent = 'app'; | ||||
|         </script> | ||||
|         {{ encore_entry_script_tags('address') }} | ||||
|     {% endblock %} | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,26 @@ | ||||
| {% extends '@ChillPerson/Household/layout.html.twig' %} | ||||
|  | ||||
| {% block title 'Edit household address'|trans %} | ||||
|  | ||||
| {% block content %} | ||||
|     <h1>{{ block('title') }}</h1> | ||||
|  | ||||
|     <div> | ||||
|         <div id="household-address"></div> | ||||
|     </div> | ||||
|  | ||||
|     {% block stylesheets %} | ||||
|         <link href="{{ asset('build/address.css') }}" type="text/css" rel="stylesheet" /> | ||||
|     {% endblock %} | ||||
|  | ||||
|     {% block js %} | ||||
|        <script type="text/javascript"> | ||||
|             window.householdId = {{ household.id|e('js') }}; | ||||
|             window.addressId = {{ address.id|e('js') }}; | ||||
|             window.mode = 'edit'; | ||||
|             window.vueRootComponent = 'app'; | ||||
|         </script> | ||||
|         {{ encore_entry_script_tags('household_address') }} | ||||
|     {% endblock %} | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -3,9 +3,22 @@ | ||||
| {% block title 'Move household'|trans %} | ||||
|  | ||||
| {% block content %} | ||||
| <h1>{{ block('title') }}</h1> | ||||
|     <h1>{{ block('title') }}</h1> | ||||
|  | ||||
| <p>Household with id {{ household.id }}</p> | ||||
|     <div> | ||||
|         <div id="household-address"></div> | ||||
|     </div> | ||||
|  | ||||
|     {% block stylesheets %} | ||||
|         <link href="{{ asset('build/address.css') }}" type="text/css" rel="stylesheet" /> | ||||
|     {% endblock %} | ||||
|  | ||||
|     {% block js %} | ||||
|        <script type="text/javascript"> | ||||
|             window.householdId = {{ household.id|e('js') }}; | ||||
|             window.vueRootComponent = 'app'; | ||||
|         </script> | ||||
|         {{ encore_entry_script_tags('household_address') }} | ||||
|     {% endblock %} | ||||
|  | ||||
| {% endblock %} | ||||
|   | ||||
| @@ -4,12 +4,67 @@ | ||||
|  | ||||
| {% block content %} | ||||
| <h1>{{ block('title') }}</h1> | ||||
| <div class="household"> | ||||
|  | ||||
| <p>Household with id {{ household.id }}</p> | ||||
|     <div class="household__address"> | ||||
|  | ||||
| <a class="sc-button bt-update"  | ||||
|   href="{{ chill_path_add_return_path('chill_person_household_address_move', { 'household_id': household.id }) }}"> | ||||
|   {{ 'Move household'|trans }} | ||||
| </a> | ||||
|         <div class="row"> | ||||
|             <div class="household__address--date"></div> | ||||
|             <div class="household__address--content"> | ||||
|                 <div class="cell"> | ||||
|                     <a class="sc-button bt-create" | ||||
|                     href="{{ chill_path_add_return_path('chill_person_household_address_move', { 'household_id': household.id }) }}"> | ||||
|                     {{ 'Move household'|trans }} | ||||
|                     </a> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         {% for address in household.addresses %} | ||||
|         <div class="row"> | ||||
|             <div class="household__address--date"> | ||||
|                 <div class="cell"> | ||||
|                     <div class="pill"> | ||||
|                     {% if address.validFrom is not empty %} | ||||
|                     {{ address.validFrom|format_date('long') }} | ||||
|                     {% endif %} | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="household__address--content"> | ||||
|                 <div class="cell"> | ||||
|                     <i class="dot"></i> | ||||
|                     <div> | ||||
|                         {% if address.isNoAddress == true %} | ||||
|                         <div class="chill_address_is_noaddress">{{ 'address.consider homeless'|trans }}</div> | ||||
|                         {% else %} | ||||
|                         <div> | ||||
|                             {% if address.street is not empty %} | ||||
|                             <div class="street"> | ||||
|                                 <i class="fa fa-fw fa-map-marker"></i> | ||||
|                                 <span class="streetNumber">{{ address.street }}</span> | ||||
|                                 {% if address.streetNumber is not empty %} | ||||
|                                     <span class="streetNumber">, {{ address.streetNumber }}</span> | ||||
|                                 {% endif %} | ||||
|                             </div> | ||||
|                             {% endif %} | ||||
|                             {% if address.postCode is not empty %} | ||||
|                             <div class="postCode"> | ||||
|                                 <span>{{ address.postCode.code }}</span> <span>{{ address.postCode.name }}</span> | ||||
|                                 <span class="country">({{ address.postCode.country.name|localize_translatable_string }})</span> | ||||
|                             </div> | ||||
|                             {% endif %} | ||||
|  | ||||
|                         </div> | ||||
|                         {% endif %} | ||||
|                         <a href="{{ path('chill_person_household_address_edit', { 'household_id': household.id, 'address_id' : address.id } ) }}" class="sc-button bt-edit"></a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         {% endfor %} | ||||
|     </div> | ||||
|  | ||||
| </div> | ||||
|  | ||||
| {% endblock %} | ||||
|   | ||||
| @@ -179,7 +179,7 @@ components: | ||||
|           readOnly: true | ||||
|         children_ids: | ||||
|           type: array | ||||
|           items:  | ||||
|           items: | ||||
|             type: integer | ||||
|           readOnly: true | ||||
|         title: | ||||
| @@ -210,7 +210,7 @@ components: | ||||
|           type: string | ||||
|           enum: | ||||
|             - 'household_position' | ||||
|            | ||||
|  | ||||
|  | ||||
| paths: | ||||
|   /1.0/person/person/{id}.json: | ||||
| @@ -259,10 +259,48 @@ paths: | ||||
|           description: "Unauthorized" | ||||
|         422: | ||||
|           description: "Invalid data: the data is a valid json, could be deserialized, but does not pass validation" | ||||
|       | ||||
|  | ||||
|   /1.0/person/person/{id}/address.json: | ||||
|     post: | ||||
|       tags: | ||||
|         - person | ||||
|       summary: post an address to a person | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The person id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               type: object | ||||
|               properties: | ||||
|                 id: | ||||
|                   type: integer | ||||
|                   description: The address id to attach to the person | ||||
|       responses: | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|         404: | ||||
|           description: "Not found" | ||||
|         200: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|  | ||||
|  | ||||
|  | ||||
|   /1.0/person/social-work/social-issue.json: | ||||
|     get: | ||||
|       tags:  | ||||
|       tags: | ||||
|         - social-issue | ||||
|       summary: Return a list of social work | ||||
|       responses: | ||||
| @@ -270,7 +308,7 @@ paths: | ||||
|           description: "ok" | ||||
|   /1.0/person/social-work/social-issue/{id}.json: | ||||
|     get: | ||||
|       tags:  | ||||
|       tags: | ||||
|         - social-issue | ||||
|       summary: Return a social issue by id | ||||
|       parameters: | ||||
| @@ -424,7 +462,7 @@ paths: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "object with validation errors" | ||||
|        | ||||
|  | ||||
|   /1.0/person/accompanying-course/{id}/participation.json: | ||||
|     post: | ||||
|       tags: | ||||
| @@ -784,6 +822,41 @@ paths: | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|  | ||||
|   /1.0/person/household.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - household | ||||
|       summary: Return a list of all household | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|  | ||||
|   /1.0/person/household/{id}.json: | ||||
|     get: | ||||
|       tags: | ||||
|         - household | ||||
|       summary: Return a household by id | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The household id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "ok" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/Household' | ||||
|         404: | ||||
|           description: "not found" | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|  | ||||
|   /1.0/person/household/members/move.json: | ||||
|     post: | ||||
|       tags: | ||||
| @@ -868,4 +941,39 @@ paths: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|                      | ||||
|  | ||||
|   /1.0/person/household/{id}/address.json: | ||||
|     post: | ||||
|       tags: | ||||
|         - household | ||||
|       summary: post an address to a household | ||||
|       parameters: | ||||
|         - name: id | ||||
|           in: path | ||||
|           required: true | ||||
|           description: The household id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               type: object | ||||
|               properties: | ||||
|                 id: | ||||
|                   type: integer | ||||
|                   description: The address id to attach to the household | ||||
|       responses: | ||||
|         401: | ||||
|           description: "Unauthorized" | ||||
|         404: | ||||
|           description: "Not found" | ||||
|         200: | ||||
|           description: "OK" | ||||
|         422: | ||||
|           description: "Unprocessable entity (validation errors)" | ||||
|         400: | ||||
|           description: "transition cannot be applyed" | ||||
|   | ||||
| @@ -7,8 +7,9 @@ module.exports = function(encore, entries) | ||||
|     encore.addAliases({ | ||||
|         ChillPersonAssets: __dirname + '/Resources/public' | ||||
|     }); | ||||
|      | ||||
|  | ||||
|     encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js'); | ||||
|     encore.addEntry('household_members_editor', __dirname + '/Resources/public/vuejs/HouseholdMembersEditor/index.js'); | ||||
|     encore.addEntry('vue_accourse', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js'); | ||||
|     encore.addEntry('household_address', __dirname + '/Resources/public/vuejs/HouseholdAddress/index.js'); | ||||
| }; | ||||
|   | ||||
| @@ -185,6 +185,7 @@ Pick a person: Choisir une personne | ||||
| No address given: Pas d'adresse renseignée | ||||
| The address has been successfully updated: L'adresse a été mise à jour avec succès | ||||
| Update address for %name%: Mettre à jour une adresse pour %name% | ||||
| Modify address for %name%: Modifier une adresse pour %name% | ||||
| Addresses'history for %name%: Historique des adresses de %name% | ||||
| Addresses'history: Historique des adresses | ||||
| New address for %name% : Nouvelle adresse pour %name% | ||||
| @@ -317,3 +318,11 @@ Show Accompanying Course: Voir le parcours | ||||
| Edit Accompanying Course: Modifier le parcours | ||||
| Create Accompanying Course: Créer un nouveau parcours | ||||
| Drop Accompanying Course: Supprimer le parcours | ||||
|  | ||||
| # Household | ||||
| Household: Ménage | ||||
| Summary: Résumé | ||||
| Members: Membres | ||||
| Addresses: Adresses | ||||
| Move household: Nouveau déménagement | ||||
| Addresses history for household: Historique des adresses | ||||
|   | ||||
		Reference in New Issue
	
	Block a user