Merge branch 'issue433_email_addPerson' into 'master'

AddPerson: email and altNames corrections and validation

See merge request Chill-Projet/chill-bundles!327
This commit is contained in:
Julien Fastré 2022-02-11 11:33:23 +00:00
commit 64fa7f2e00
12 changed files with 100 additions and 51 deletions

View File

@ -11,14 +11,19 @@ and this project adheres to
## Unreleased
<!-- write down unreleased development here -->
* [person] accompanying course work: fix on-the-fly update of thirdParty
* [on-the-fly] close modal only after validation
* [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433)
* change order for accompanying course work list
* [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432)
* ajoute un ordre dans les localisation (api)
* [pick entity]: fix translations in modal (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/419)
## Test releases
### test release 2021-02-01
>>>>>>> master
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
* renomme date de début en date d'ouverture dans le formulaire parcours

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpFoundation\Request;
/**
@ -19,7 +21,7 @@ use Symfony\Component\HttpFoundation\Request;
*/
class LocationApiController extends ApiController
{
public function customizeQuery(string $action, Request $request, $query): void
protected function customizeQuery(string $action, Request $request, $query): void
{
$query
->leftJoin('e.locationType', 'lt')
@ -31,4 +33,14 @@ class LocationApiController extends ApiController
)
);
}
/**
* @param QueryBuilder $query
* @param mixed $_format
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format)
{
return $query
->addOrderBy('e.name', 'ASC');
}
}

View File

@ -90,7 +90,7 @@ export default {
OnTheFlyThirdparty,
OnTheFlyCreate
},
props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'isDead', 'parent', 'canCloseModal'],
props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'isDead', 'parent'],
emits: ['saveFormOnTheFly'],
data() {
return {
@ -162,16 +162,6 @@ export default {
return 'entity-' + this.type + ' badge-' + this.type;
}
},
watch: {
canCloseModal: {
handler: function(val, oldVal) {
if (val) {
this.closeModal();
}
},
deep: true
}
},
methods: {
closeModal() {
this.modal.showModal = false;

View File

@ -28,7 +28,7 @@
</a>
</li>
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" :canCloseModal="canCloseOnTheFlyModal"></on-the-fly></li>
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
<li>
<button v-if="!participation.endDate"
class="btn btn-sm btn-remove"
@ -90,7 +90,6 @@ export default {
hLevel: 1
}
},
canCloseOnTheFlyModal: false
}
},
computed: {
@ -120,12 +119,14 @@ export default {
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = payload.data.gender;
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$store.dispatch('addPerson', { target: payload.target, body: response });
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
@ -143,10 +144,10 @@ export default {
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch('PATCH', `/api/1.0/third-party/third-party/${payload.data.id}.json`, body)
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {

View File

@ -26,7 +26,7 @@
<template v-slot:record-actions>
<ul class="record_actions">
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
</ul>
</template>
</third-party-render-box>
@ -52,7 +52,7 @@
<template v-slot:record-actions>
<ul class="record_actions">
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
</ul>
</template>
</person-render-box>
@ -92,7 +92,7 @@
<template v-slot:record-actions>
<ul class="record_actions">
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
</ul>
</template>
</third-party-render-box>
@ -114,7 +114,7 @@
<template v-slot:record-actions>
<ul class="record_actions">
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" :canCloseModal="canCloseOnTheFlyModal"></on-the-fly></li>
<li><on-the-fly :type="accompanyingCourse.requestor.type" :id="accompanyingCourse.requestor.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
</ul>
</template>
</person-render-box>
@ -189,7 +189,6 @@ export default {
uniq: true,
}
},
canCloseOnTheFlyModal: false
}
},
computed: {
@ -261,12 +260,14 @@ export default {
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = payload.data.gender;
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
@ -284,10 +285,10 @@ export default {
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch('PATCH', `/api/1.0/third-party/third-party/${payload.data.id}.json`, body)
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {

View File

@ -35,7 +35,7 @@
:id="resource.resource.id"
action="edit"
@saveFormOnTheFly="saveFormOnTheFly"
:canCloseModal="canCloseOnTheFlyModal">
ref="onTheFly">
</on-the-fly>
</li>
<li>
@ -82,7 +82,7 @@
:id="resource.resource.id"
action="edit"
@saveFormOnTheFly="saveFormOnTheFly"
:canCloseModal="canCloseOnTheFlyModal">
ref="onTheFly">
</on-the-fly>
</li>
<li>
@ -116,11 +116,6 @@ export default {
},
props: ['resource'],
emits: ['remove'],
data() {
return {
canCloseOnTheFlyModal: false
}
},
computed: {
parent() {
return {
@ -152,12 +147,14 @@ export default {
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = payload.data.gender;
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
@ -175,10 +172,10 @@ export default {
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch('PATCH', `/api/1.0/third-party/third-party/${payload.data.id}.json`, body)
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {

View File

@ -211,7 +211,7 @@
<template v-slot:record-actions>
<ul class="record_actions">
<li><on-the-fly :type="thirdparty.type" :id="thirdparty.id" action="show"></on-the-fly></li>
<li><on-the-fly :type="thirdparty.type" :id="thirdparty.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly"></on-the-fly></li>
<li><on-the-fly :type="thirdparty.type" :id="thirdparty.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
<li>
<button :title="$t('remove_thirdparty')" class="btn btn-sm btn-remove" @click="removeThirdParty(thirdparty)" />
</li>
@ -286,6 +286,8 @@ import ListWorkflowModal from 'ChillMainAssets/vuejs/_components/EntityWorkflow/
import PickWorkflow from 'ChillMainAssets/vuejs/_components/EntityWorkflow/PickWorkflow.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
const i18n = {
messages: {
@ -476,15 +478,27 @@ export default {
},
saveFormOnTheFly(payload) {
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = 'resource';
this.$store.dispatch('patchOnTheFly', payload)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
let body = { type: payload.type };
body.name = payload.data.text;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('updateThirdParty', response)
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'})
this.$toast.open({message: 'An error occurred'});
}
});
})
}
}
};

View File

@ -1,7 +1,9 @@
import { createApp } from 'vue';
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
import { store } from './store';
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n'
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n';
import VueToast from 'vue-toast-notification';
import 'vue-toast-notification/dist/theme-sugar.css';
import App from './App.vue';
const i18n = _createI18n(personMessages);
@ -10,6 +12,12 @@ const app = createApp({
template: `<app></app>`,
})
.use(store)
.use(VueToast, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true
})
.use(i18n)
.component('app', App)
.mount('#accompanying_course_work_edit');

View File

@ -266,6 +266,14 @@ const store = createStore({
state.thirdParties.push(unexistings[i]);
}
},
updateThirdParty(state, thirdParty) {
for (let t of state.thirdParties) {
if (t.id === thirdParty.id){
state.thirdParties = state.thirdParties.filter(t => t.id !== thirdParty.id);
state.thirdParties.push(thirdParty);
}
}
},
removeThirdParty(state, thirdParty) {
state.thirdParties = state.thirdParties
.filter(t => t.id !== thirdParty.id);
@ -278,6 +286,10 @@ const store = createStore({
},
},
actions: {
updateThirdParty({ commit }, payload) {
console.log(payload);
commit('updateThirdParty', payload);
},
getReachablesGoalsForAction({ getters, commit, dispatch }) {
let
socialActionId = getters.socialAction.id,

View File

@ -69,7 +69,7 @@
:buttonText="$t('onthefly.create.button', {q: query})"
action="create"
@saveFormOnTheFly="saveFormOnTheFly"
:canCloseModal="canCloseOnTheFlyModal">
ref="onTheFly">
</on-the-fly>
</div>
@ -121,7 +121,6 @@ export default {
selected: [],
priorSuggestion: {}
},
canCloseOnTheFlyModal: false
}
},
computed: {
@ -271,7 +270,7 @@ export default {
makeFetch('POST', '/api/1.0/person/person.json', data)
.then(response => {
this.newPriorSuggestion(response);
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
@ -287,7 +286,7 @@ export default {
makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
.then(response => {
this.newPriorSuggestion(response);
this.canCloseOnTheFlyModal = true;
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
@ -299,7 +298,6 @@ export default {
}
})
}
this.canCloseOnTheFlyModal = false;
}
},
}

View File

@ -43,10 +43,11 @@
<label for="firstname">{{ $t('person.firstname') }}</label>
</div>
<div v-for="(a) in config.altNames" :key="a.key" class="form-floating mb-3">
<div v-for="(a, i) in config.altNames" :key="a.key" class="form-floating mb-3">
<input
class="form-control form-control-lg"
:id="a.key"
:value="personAltNamesLabels[i]"
@input="onAltNameInput"
/>
<label :for="a.key">{{ a.labels.fr }}</label>
@ -199,6 +200,9 @@ export default {
},
feminized() {
return (this.person.gender === 'woman')? 'e' : '';
},
personAltNamesLabels() {
return this.person.altNames.map(a => a ? a.label : '');
}
},
mounted() {

View File

@ -91,6 +91,7 @@ class PersonJsonNormalizer implements
'deathdate',
'center',
'altNames',
'email'
];
$fields = array_filter(
@ -161,6 +162,11 @@ class PersonJsonNormalizer implements
}
}
break;
case 'email':
$person->setEmail($data[$item]);
break;
}
}
@ -189,6 +195,7 @@ class PersonJsonNormalizer implements
'centers' => $this->normalizer->normalize($this->centerResolverManager->resolveCenters($person), $format, $context),
'phonenumber' => $person->getPhonenumber(),
'mobilenumber' => $person->getMobilenumber(),
'email' => $person->getEmail(),
'altNames' => $this->normalizeAltNames($person->getAltNames()),
'gender' => $person->getGender(),
'current_household_address' => $this->normalizer->normalize($person->getCurrentHouseholdAddress(), $format, $context),