Merge branch 'address_refactoring' into add-location-period

This commit is contained in:
2021-08-08 22:31:18 +02:00
22 changed files with 339 additions and 561 deletions

View File

@@ -93,7 +93,8 @@ section.chill-entity {
font-style: italic;
}
span.address-valid {
.address-valid {
margin-top: 2em;
&.date-since {}
&.date-until {}
}

View File

@@ -19,7 +19,7 @@
</div>
<add-address
v-bind:key="addAddress.type"
v-bind:key="context.entity.type"
v-bind:context="context"
v-bind:options="addAddress.options"
v-bind:result="addAddress.result"
@@ -28,6 +28,13 @@
</template>
<script>
/*
* Address component is a uniq component for many contexts.
* Allow to create/attach/edit an address to
* - a person (new or edit address),
* - a household (move or edit address)
*
* */
import AddAddress from './components/AddAddress.vue';
export default {
@@ -39,40 +46,44 @@ export default {
return {
context: {
edit: window.mode === 'edit',
personId: window.personId,
addressId: window.addressId,
entity: {
type: window.entityType,
id: window.entityId
},
addressId: window.addressId | null,
backUrl: window.backUrl,
},
addAddress: {
options: {
/// Options override default.
/// null value take default component value
/// null value take default component value defined in AddAddress data()
button: {
text: {
/// if create or edit address
create: window.buttonText || null,
edit: window.buttonText || null
},
type: window.button.type || null,
size: window.button.size || null,
display: window.button.display
type: window.buttonType || null,
size: window.buttonSize || null,
display: window.buttonDisplay //boolean, default: true
},
/// Modal title text if create or edit address (trans chain, see i18n)
title: {
create: window.modalTitle || null,
edit: window.modalTitle || null
},
/// Display each step in page or Modal
bindModal: {
step1: window.binModalStep1,
step2: window.binModalStep2
step1: window.binModalStep1, //boolean, default: true
step2: window.binModalStep2 //boolean, default: true
},
// Options only for root parent component
displayResult: true,
redirectToBackUrl: true
},
type: 'person',
result: null // <== returned from addAddress component
}
}

View File

@@ -125,31 +125,6 @@ const postPostalCode = (postalCode) => {
});
};
/*
* 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
@@ -174,6 +149,5 @@ export {
postAddress,
patchAddress,
postPostalCode,
postAddressToPerson,
getAddress
};

View File

@@ -1,5 +1,6 @@
<template>
<!-- start with a button -->
<button v-if="step1WithModal"
@click="openShowPane"
class="btn" :class="getClassButton"
@@ -28,6 +29,7 @@
v-bind:options="this.options"
v-bind:default="this.default"
v-bind:entity="this.entity"
v-bind:valid="this.valid"
v-bind:flag="this.flag"
ref="showAddress">
</show-address>
@@ -53,6 +55,7 @@
v-bind:options="this.options"
v-bind:default="this.default"
v-bind:entity="this.entity"
v-bind:valid="this.valid"
v-bind:flag="this.flag"
ref="showAddress"
v-bind:insideModal="false" @openEditPane="openEditPane"
@@ -117,13 +120,11 @@
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { getAddress, fetchCountries, fetchCities, fetchReferenceAddresses, patchAddress, postAddress, postPostalCode } from '../api';
import { postAddressToPerson } from "ChillPersonAssets/vuejs/_api/AddAddress/Person.js";
import { postAddressToHousehold } from "ChillPersonAssets/vuejs/_api/AddAddress/Household.js";
import ShowAddress from './ShowAddress.vue';
import EditAddress from './EditAddress.vue';
import {
getAddress,
fetchCountries, fetchCities, fetchReferenceAddresses,
patchAddress, postAddress, postPostalCode, postAddressToPerson
} from '../api'
export default {
name: "AddAddress",
@@ -182,7 +183,7 @@ export default {
},
},
valid: {
from: null,
from: new Date(),
to: null
},
errorMsg: []
@@ -227,7 +228,7 @@ export default {
},
mounted() {
if (!this.step1WithModal) {
console.log('Mounted now !');
//console.log('Mounted now !');
this.openShowPane();
}
},
@@ -238,9 +239,11 @@ export default {
*/
openShowPane() {
console.log('open the Show Panel');
if (this.context.addressId) {
if (this.context.edit) {
this.getInitialAddress(this.context.addressId);
}
// when create new address, start first with editPane
if ( this.context.edit === false
&& this.flag.editPane === false
@@ -260,7 +263,7 @@ export default {
},
closeEditPane() {
console.log('close the Edit Panel (with validation)');
console.log('close the Edit Panel');
this.applyChanges();
this.flag.showPane = true;
this.flag.editPane = false;
@@ -359,12 +362,12 @@ export default {
},
/*
* When changes are validated,
* When changes are validated (get out step2 edit pane, button valid),
* apply some transformations before asyncing with backend
* from entity.selected to entity.address
*/
applyChanges() {
applyChanges()
{
let newAddress = {
'isNoAddress': this.entity.selected.isNoAddress,
'street': this.entity.selected.isNoAddress ? '' : this.entity.selected.address.street,
@@ -395,21 +398,71 @@ export default {
}
if (this.context.edit) {
this.updateAddress({ addressId: this.context.addressId, newAddress: newAddress });
this.updateAddress({
addressId: this.context.addressId,
newAddress: newAddress
});
} else {
this.addAddress(newAddress);
}
},
/*
* Async POST transactions,
* creating new address, and receive backend datas when promise is resolved
*/
addAddress(payload)
{
this.flag.loading = true;
if ('newPostcode' in payload) {
let postcodeBody = payload.newPostcode;
if (this.context.entity.type === 'person') {
postcodeBody = Object.assign(postcodeBody, {'origin': 3});
}
postPostalCode(postcodeBody)
.then(postalCode => {
let body = payload;
body.postcode = {'id': postalCode.id },
postAddress(body)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
})
} else {
postAddress(payload)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
}
},
/*
* Async PATCH transactions,
* then update existing address with backend datas when promise is resolved
*/
updateAddress(payload) {
updateAddress(payload)
{
// TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode
this.flag.loading = true;
if ('newPostcode' in payload.newAddress) {
let postcodeBody = payload.newAddress.newPostcode;
postcodeBody = Object.assign(postcodeBody, {'origin': 3});
@@ -421,6 +474,7 @@ export default {
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
@@ -434,6 +488,7 @@ export default {
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
@@ -444,93 +499,101 @@ export default {
},
/*
* Async POST transactions,
* creating new address, and receive backend datas when promise is resolved
* When submit address
* (get out step1 show pane, submit button)
*/
addAddress(payload) {
this.flag.loading = true;
if('newPostcode' in payload){
let postcodeBody = payload.newPostcode;
postcodeBody = Object.assign(postcodeBody, {'origin': 3});
postPostalCode(postcodeBody)
.then(postalCode => {
let body = payload;
body.postcode = {'id': postalCode.id},
postAddress(body)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
resolve();
this.flag.loading = false;
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
})
} else {
postAddress(payload)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
resolve();
this.flag.loading = false;
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
}
},
/*
* When submited
*/
submitAddress() {
console.log('@@@ CLICK button submitAddress');
this.addDateToAddressAndAddressToPerson({
personId: this.context.personId,
submitAddress()
{
let payload = {
entityId: this.context.entity.id,
addressId: this.entity.address.address_id,
body: { validFrom: { datetime: `${this.$refs.showAddress.validFrom}T00:00:00+0100`}},
body: {
validFrom: {
datetime: `${this.valid.from.toISOString().split('T')[0]}T00:00:00+0100`
}
},
backUrl: this.context.backUrl
});
}
console.log('@@@ CLICK button submitAddress for', this.context.entity.type, 'with payload', payload);
this.addDateToAddressAndAddressTo(payload, this.context.entity.type);
this.initForm();
this.flag.showPane = false;
},
addDateToAddressAndAddressToPerson(payload) {
console.log('addDateToAddressAndAddressToPerson payload', payload);
addDateToAddressAndAddressTo(payload, postTo)
{
console.log('addDateToAddressAndAddressTo', postTo)
this.flag.loading = true;
patchAddress(payload.addressId, payload.body)
.then(address => new Promise((resolve, reject) => {
this.valid.from = address.validFrom;
resolve();
}).then(
postAddressToPerson(payload.personId, payload.addressId)
.then(person => new Promise((resolve, reject) => {
console.log('commit addAddressToPerson !!!', person);
this.$props.result = person;
this.flag.loading = false;
this.flag.success = true;
if (this.options.redirectToBackUrl) {
window.location.assign(payload.backUrl);
}
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
})
))
this.valid.from = address.validFrom;
resolve();
})
.then(
this.postAddressTo(payload, postTo)
)
)
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
}
},
postAddressTo(payload, postTo)
{
console.log('postAddressTo', postTo);
if (!this.context.edit) {
switch (postTo) {
case 'household':
postAddressToHousehold(payload.entityId, payload.addressId)
.then(household => new Promise((resolve, reject) => {
console.log('commit addAddressToHousehold', household);
this.flag.loading = false;
this.flag.success = true;
if (this.options.redirectToBackUrl) {
window.location.assign(payload.backUrl);
}
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
})
;
break;
case 'person':
default:
postAddressToPerson(payload.entityId, payload.addressId)
.then(person => new Promise((resolve, reject) => {
console.log('commit addAddressToPerson !!!', person);
this.flag.loading = false;
this.flag.success = true;
if (this.options.redirectToBackUrl) {
window.location.assign(payload.backUrl);
}
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
})
;
}
} else {
// address is already posted, just finish !
if (this.options.redirectToBackUrl) {
window.location.assign(payload.backUrl);
}
}
},
}
}
</script>

View File

@@ -31,7 +31,7 @@ export default {
},
computed: {
sortedCountries() {
console.log('sorted countries');
//console.log('sorted countries');
const countries = this.entity.loaded.countries;
let sortedCountries = [];
sortedCountries.push(...countries.filter(c => c.countryCode === 'FR'))
@@ -56,7 +56,7 @@ export default {
return name.fr //TODO multilang
},
selectCountry(value) {
console.log('select country', value);
//console.log('select country', value);
this.entity.selected.country = value;
this.$emit('getCities', value);
}

View File

@@ -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>

View File

@@ -3,7 +3,13 @@
<div v-if="insideModal == false" class="loading">
<i v-if="flag.loading" class="fa fa-circle-o-notch fa-spin fa-2x fa-fw"></i>
<span class="sr-only">Loading...</span>
<span class="sr-only">{{ $t('loading') }}</span>
</div>
<div v-if="errorMsg && errorMsg.length > 0" class="alert alert-danger">
{{ errorMsg }}
</div>
<div v-if="flag.success" class="alert alert-success">
{{ $t(getSuccessText) }}
</div>
<div class="address multiline">
@@ -59,24 +65,15 @@
</div>
<div v-if="!context.edit" class='address-valid date-since'>
<h3>{{ $t('date') }}</h3>
<h3>{{ $t(getValidFromDateText) }}</h3>
<div class="input-group mb-3">
<span class="input-group-text" id="validFrom"><i class="fa fa-fw fa-calendar"></i></span>
<input type="date" class="form-control form-control-lg" name="validFrom"
v-bind:placeholder="$t('validFrom')"
v-bind:placeholder="$t(getValidFromDateText)"
v-model="validFrom"
aria-describedby="validFrom"
/>
</div>
<!--div v-if="errorMsg.length > 0">
{{ errors }}
</div-->
<div v-if="flag.loading">
{{ $t('loading') }}
</div>
<div v-if="flag.success">
{{ $t('person_address_creation_success') }}
</div>
</div>
</div>
@@ -95,7 +92,7 @@
</li>
<li>
<a class="btn btn-save"
@click.prevent="$emit('submitAddress', { getSubmited , flag })">
@click.prevent="$emit('submitAddress')">
{{ $t('action.save')}}
</a>
</li>
@@ -103,6 +100,7 @@
</template>
<script>
import { dateToISO, ISOToDate, ISOToDatetime } from 'ChillMainAssets/chill/js/date.js';
export default {
name: 'ShowAddress',
@@ -112,10 +110,11 @@ export default {
'default',
'flag',
'entity',
'valid',
'errorMsg',
'insideModal'
],
emits: ['openEditPane', 'submitAddress', 'validFrom'],
emits: ['openEditPane', 'submitAddress'], //?
computed: {
address() {
return this.entity.address;
@@ -132,8 +131,28 @@ export default {
getSubmited() {
return this.entity.address;
},
validFrom() {
return new Date().toISOString().split('T')[0];
validFrom: {
set(value) {
this.valid.from = ISOToDate(value);
},
get() {
return dateToISO(this.valid.from);
}
},
getValidFromDateText() {
return (this.context.entity.type === 'household') ? 'move_date' : 'validFrom';
},
getSuccessText() {
switch (this.context.entity.type) {
/*
case 'household':
return (this.context.edit) ? 'household_address_edit_success' : 'household_address_move_success';
case 'person':
return (this.context.edit) ? 'person_address_edit_success' : 'person_address_creation_success';
*/
default:
return (this.context.edit) ? 'address_edit_success' : 'address_new_success';
}
}
}
};

View File

@@ -29,11 +29,24 @@ const addressMessages = {
postalCode_name: 'Nom',
postalCode_code: 'Code postal',
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',
loading: 'chargement en cours...',
address_new_success: 'La nouvelle adresse est enregistrée',
address_edit_success: 'L\'adresse a été mise à jour',
// person specific
add_an_address_to_person: 'Ajouter l\'adresse à la personne',
person_address_creation_success: 'La nouvelle adresse de la personne est enregistrée',
loading: 'chargement en cours...'
person_address_edit_success: 'L\'adresse de la personne a été mise à jour',
// household specific
move_date: 'Date du déménagement',
select_a_existing_address: 'Sélectionner une adresse existante',
add_an_address_to_household: 'Enregistrer',
household_address_move_success: 'La nouvelle adresse du ménage est enregistrée',
household_address_edit_success: 'L\'adresse du ménage a été mise à jour',
}
};