vue_activity location: add NewLocation fields, submit activity form with hidden field (+)

This commit is contained in:
Mathieu Jaumotte 2021-10-15 09:09:47 +02:00
parent 4d4662a634
commit e6845326d7
9 changed files with 175 additions and 11 deletions

View File

@ -6,6 +6,7 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityPresence; use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\DocStoreBundle\Form\StoredObjectType; use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\MainBundle\Entity\Location;
use Chill\MainBundle\Form\Type\ChillCollectionType; use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\CommentType; use Chill\MainBundle\Form\Type\CommentType;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
@ -303,7 +304,20 @@ class ActivityType extends AbstractType
} }
if ($activityType->isVisible('location')) { if ($activityType->isVisible('location')) {
$builder->add('location', HiddenType::class); $builder->add('location', HiddenType::class)
->get('location')
->addModelTransformer(new CallbackTransformer(
function (?Location $location): string {
if (null === $location) {
return '';
}
return $location->getId();
},
function (?string $id): Location {
return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]);
}
))
;
} }
if ($activityType->isVisible('emergency')) { if ($activityType->isVisible('emergency')) {

View File

@ -36,9 +36,28 @@ const getLocationTypes = () => {
}); });
}; };
/*
* Post a Location
*/
const postLocation = (body) => {
const url = `/api/1.0/main/location.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');
});
};
export { export {
getSocialIssues, getSocialIssues,
getSocialActionByIssue, getSocialActionByIssue,
getLocations, getLocations,
getLocationTypes getLocationTypes,
postLocation
}; };

View File

@ -21,7 +21,7 @@
</VueMultiselect> </VueMultiselect>
<!-- <!--
--> -->
<new-location></new-location> <new-location @saveNewLocation="saveNewLocation"></new-location>
</div> </div>
</div> </div>
</teleport> </teleport>
@ -31,7 +31,7 @@
import { mapState } from "vuex"; import { mapState } from "vuex";
import VueMultiselect from 'vue-multiselect'; import VueMultiselect from 'vue-multiselect';
import NewLocation from './Location/NewLocation.vue'; import NewLocation from './Location/NewLocation.vue';
import { getLocations } from '../api.js'; import { getLocations, postLocation } from '../api.js';
export default { export default {
name: "Location", name: "Location",
@ -51,7 +51,7 @@ export default {
return this.activity.location; return this.activity.location;
}, },
set(value) { set(value) {
this.$store.commit('updateLocation', value); this.$store.dispatch('updateLocation', value);
} }
} }
}, },
@ -62,13 +62,40 @@ export default {
getLocationsList() { getLocationsList() {
getLocations().then(response => new Promise(resolve => { getLocations().then(response => new Promise(resolve => {
console.log('getLocations', response); console.log('getLocations', response);
this.locations = response.results; this.locations = response.results.filter(l => l.availableForUsers === true);
resolve(); resolve();
})) }))
}, },
customLabel(value) { customLabel(value) {
return `${value.locationType.title.fr} ${value.name}`; return `${value.locationType.title.fr} ${value.name}`;
},
saveNewLocation(selected) {
console.log('saveNewLocation', selected);
console.log('post location')
let body = {
type: 'location',
name: selected.name,
address: { id: selected.addressId },
locationtype: { id: selected.type },
email: selected.email,
phonenumber1: selected.phonenumber1,
phonenumber2: selected.phonenumber2,
}
//this.$store.dispatch('addLocationSelected', body);
postLocation(body).then(location => new Promise(resolve => {
this.locations.push(location);
this.location.set(location);
resolve();
}));
} }
} }
} }
/*
*
* TODO
* - multiselect, n'affiche pas l'item choisi
* - addAddress, les multiselect pays/localité/adresse ne se remplissent pas
*
*/
</script> </script>

View File

@ -40,9 +40,22 @@
<label>Type</label> <label>Type</label>
</div> </div>
<div class="form-floating mb-3">
<input class="form-control form-control-lg" id="phonenumber1" v-model="inputPhonenumber1" placeholder="edit me" />
<label for="phonenumber1">Téléphone</label>
</div>
<div class="form-floating mb-3" v-if="hasPhonenumber1">
<input class="form-control form-control-lg" id="phonenumber2" v-model="inputPhonenumber2" placeholder="edit me" />
<label for="phonenumber2">Autre téléphone</label>
</div>
<div class="form-floating mb-3">
<input class="form-control form-control-lg" id="email" v-model="inputEmail" placeholder="edit me" />
<label for="email">Adresse courriel</label>
</div>
</template> </template>
<template v-slot:footer> <template v-slot:footer>
<button class="btn btn-save">Enregistrer</button> <button class="btn btn-save" @click.prevent="$emit('saveNewLocation', selected)">Enregistrer</button>
</template> </template>
</modal> </modal>
@ -61,12 +74,16 @@ export default {
Modal, Modal,
AddAddress, AddAddress,
}, },
emits: ['saveNewLocation'],
data() { data() {
return { return {
selected: { selected: {
type: {}, type: {},
name: null, name: null,
addressId: null addressId: null,
phonenumber1: null,
phonenumber2: null,
email: null,
}, },
locationTypes: [], locationTypes: [],
modal: { modal: {
@ -76,10 +93,10 @@ export default {
addAddress: { addAddress: {
options: { options: {
button: { button: {
text: { create: 'Créer une adresse' }, text: { create: 'Créer une adresse', edit: "Modifier l'adresse" },
size: 'btn-sm' size: 'btn-sm'
}, },
title: { create: 'Créer une adresse' }, title: { create: 'Créer une adresse', edit: "Modifier l'adresse" },
}, },
context: { context: {
target: { //name, id target: { //name, id
@ -107,6 +124,33 @@ export default {
set(value) { set(value) {
this.selected.name = value; this.selected.name = value;
} }
},
inputEmail: {
get() {
return this.selected.email;
},
set(value) {
this.selected.email = value;
}
},
inputPhonenumber1: {
get() {
return this.selected.phonenumber1;
},
set(value) {
this.selected.phonenumber1 = value;
}
},
inputPhonenumber2: {
get() {
return this.selected.phonenumber2;
},
set(value) {
this.selected.phonenumber2 = value;
}
},
hasPhonenumber1() {
return this.selected.phonenumber1 !== null && this.selected.phonenumber1 !== "";
} }
}, },
mounted() { mounted() {
@ -116,7 +160,7 @@ export default {
getLocationTypesList() { getLocationTypesList() {
getLocationTypes().then(response => new Promise(resolve => { getLocationTypes().then(response => new Promise(resolve => {
console.log('getLocationTypes', response); console.log('getLocationTypes', response);
this.locationTypes = response.results; this.locationTypes = response.results.filter(t => t.availableForUsers === true);
resolve(); resolve();
})) }))
}, },
@ -125,6 +169,9 @@ export default {
}, },
submitNewAddress(payload) { submitNewAddress(payload) {
console.log('submitNewAddress', payload); console.log('submitNewAddress', payload);
this.selected.addressId = payload.addressId;
this.addAddress.context.addressId = payload.addressId;
this.addAddress.context.edit = true;
} }
} }
} }

View File

@ -177,6 +177,12 @@ const store = createStore({
break; break;
}; };
commit('removePersonInvolved', payload); commit('removePersonInvolved', payload);
},
updateLocation({ commit }, value) {
console.log('### action: updateLocation', value);
let hiddenLocation = document.getElementById("chill_activitybundle_activity_location");
hiddenLocation.value = value.id;
commit('updateLocation', value);
} }
} }
}); });

View File

@ -461,6 +461,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
'methods' => [ 'methods' => [
Request::METHOD_GET => true, Request::METHOD_GET => true,
Request::METHOD_HEAD => true, Request::METHOD_HEAD => true,
Request::METHOD_POST => true,
] ]
], ],

View File

@ -9,10 +9,14 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/** /**
* @ORM\Table(name="chill_main_location") * @ORM\Table(name="chill_main_location")
* @ORM\Entity(repositoryClass=LocationRepository::class) * @ORM\Entity(repositoryClass=LocationRepository::class)
* @DiscriminatorMap(typeProperty="type", mapping={
* "location"=Location::class
* })
*/ */
class Location implements TrackCreationInterface, TrackUpdateInterface class Location implements TrackCreationInterface, TrackUpdateInterface
{ {

View File

@ -5,10 +5,14 @@ namespace Chill\MainBundle\Entity;
use Chill\MainBundle\Repository\LocationTypeRepository; use Chill\MainBundle\Repository\LocationTypeRepository;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/** /**
* @ORM\Table(name="chill_main_location_type") * @ORM\Table(name="chill_main_location_type")
* @ORM\Entity(repositoryClass=LocationTypeRepository::class) * @ORM\Entity(repositoryClass=LocationTypeRepository::class)
* @DiscriminatorMap(typeProperty="type", mapping={
* "location-type"=LocationType::class
* })
*/ */
class LocationType class LocationType
{ {

View File

@ -548,6 +548,48 @@ paths:
description: "ok" description: "ok"
401: 401:
description: "Unauthorized" description: "Unauthorized"
post:
tags:
- location
summary: create a new location
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: string
name:
type: string
phonenumber1:
type: string
phonenumber2:
type: string
email:
type: string
address:
type: object
properties:
id:
type: integer
locationtype:
type: object
properties:
id:
type: integer
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/location-type.json: /1.0/main/location-type.json:
get: get: