diff --git a/src/Bundle/ChillActivityBundle/Form/ActivityType.php b/src/Bundle/ChillActivityBundle/Form/ActivityType.php index 24b3c7ab6..19d53c262 100644 --- a/src/Bundle/ChillActivityBundle/Form/ActivityType.php +++ b/src/Bundle/ChillActivityBundle/Form/ActivityType.php @@ -6,6 +6,7 @@ use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\ActivityPresence; use Chill\ActivityBundle\Entity\ActivityReason; use Chill\DocStoreBundle\Form\StoredObjectType; +use Chill\MainBundle\Entity\Location; use Chill\MainBundle\Form\Type\ChillCollectionType; use Chill\MainBundle\Form\Type\CommentType; use Chill\PersonBundle\Entity\Person; @@ -303,7 +304,20 @@ class ActivityType extends AbstractType } 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')) { diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js index af8875f0d..9dab14ef1 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js @@ -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 { getSocialIssues, getSocialActionByIssue, getLocations, - getLocationTypes + getLocationTypes, + postLocation }; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue index f042983e1..de6ce961d 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue @@ -21,7 +21,7 @@ - + @@ -31,7 +31,7 @@ import { mapState } from "vuex"; import VueMultiselect from 'vue-multiselect'; import NewLocation from './Location/NewLocation.vue'; -import { getLocations } from '../api.js'; +import { getLocations, postLocation } from '../api.js'; export default { name: "Location", @@ -51,7 +51,7 @@ export default { return this.activity.location; }, set(value) { - this.$store.commit('updateLocation', value); + this.$store.dispatch('updateLocation', value); } } }, @@ -62,13 +62,40 @@ export default { getLocationsList() { getLocations().then(response => new Promise(resolve => { console.log('getLocations', response); - this.locations = response.results; + this.locations = response.results.filter(l => l.availableForUsers === true); resolve(); })) }, customLabel(value) { 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 +* +*/ diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue index 498967584..341255136 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location/NewLocation.vue @@ -40,9 +40,22 @@ +
+ + +
+
+ + +
+
+ + +
+ @@ -61,12 +74,16 @@ export default { Modal, AddAddress, }, + emits: ['saveNewLocation'], data() { return { selected: { type: {}, name: null, - addressId: null + addressId: null, + phonenumber1: null, + phonenumber2: null, + email: null, }, locationTypes: [], modal: { @@ -76,10 +93,10 @@ export default { addAddress: { options: { button: { - text: { create: 'Créer une adresse' }, + text: { create: 'Créer une adresse', edit: "Modifier l'adresse" }, size: 'btn-sm' }, - title: { create: 'Créer une adresse' }, + title: { create: 'Créer une adresse', edit: "Modifier l'adresse" }, }, context: { target: { //name, id @@ -107,6 +124,33 @@ export default { set(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() { @@ -116,7 +160,7 @@ export default { getLocationTypesList() { getLocationTypes().then(response => new Promise(resolve => { console.log('getLocationTypes', response); - this.locationTypes = response.results; + this.locationTypes = response.results.filter(t => t.availableForUsers === true); resolve(); })) }, @@ -125,6 +169,9 @@ export default { }, submitNewAddress(payload) { console.log('submitNewAddress', payload); + this.selected.addressId = payload.addressId; + this.addAddress.context.addressId = payload.addressId; + this.addAddress.context.edit = true; } } } diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js index 57dc26918..415c5a359 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js @@ -177,6 +177,12 @@ const store = createStore({ break; }; 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); } } }); diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 17e341b09..4f54d86bb 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -461,6 +461,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, 'methods' => [ Request::METHOD_GET => true, Request::METHOD_HEAD => true, + Request::METHOD_POST => true, ] ], diff --git a/src/Bundle/ChillMainBundle/Entity/Location.php b/src/Bundle/ChillMainBundle/Entity/Location.php index 7a8e37750..2a88a4ae5 100644 --- a/src/Bundle/ChillMainBundle/Entity/Location.php +++ b/src/Bundle/ChillMainBundle/Entity/Location.php @@ -9,10 +9,14 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * @ORM\Table(name="chill_main_location") * @ORM\Entity(repositoryClass=LocationRepository::class) + * @DiscriminatorMap(typeProperty="type", mapping={ + * "location"=Location::class + * }) */ class Location implements TrackCreationInterface, TrackUpdateInterface { diff --git a/src/Bundle/ChillMainBundle/Entity/LocationType.php b/src/Bundle/ChillMainBundle/Entity/LocationType.php index 12646aaf3..6510d5c22 100644 --- a/src/Bundle/ChillMainBundle/Entity/LocationType.php +++ b/src/Bundle/ChillMainBundle/Entity/LocationType.php @@ -5,10 +5,14 @@ namespace Chill\MainBundle\Entity; use Chill\MainBundle\Repository\LocationTypeRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; /** * @ORM\Table(name="chill_main_location_type") * @ORM\Entity(repositoryClass=LocationTypeRepository::class) + * @DiscriminatorMap(typeProperty="type", mapping={ + * "location-type"=LocationType::class + * }) */ class LocationType { diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml index daddcf36b..7c9a5aa56 100644 --- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml @@ -548,6 +548,48 @@ paths: description: "ok" 401: 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: get: