diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index 2eb04fca9..ec53cff1b 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -284,12 +284,8 @@ class CalendarController extends AbstractController $entity = new Calendar(); if ($request->query->has('mainUser')) { $entity->setMainUser($this->userRepository->find($request->query->getInt('mainUser'))); - } else { - $entity->setMainUser($this->getUser()); } - dump($entity); - // if ($user instanceof User) { // $entity->setPerson($user); // } diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index e6c5a8e97..63803efda 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -172,6 +172,29 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface return $this; } + public function addUser(User $user): self + { + if (!$this->getUsers()->contains($user)) { + $this->addInvite((new Invite())->setUser($user)); + } + + return $this; + } + + public function removeUser(User $user): self + { + if (!$this->getUsers()->contains($user)) { + return $this; + } + + $invite = $this->invites + ->filter(function (Invite $invite) use ($user) { return $invite->getUser() === $user; }) + ->first(); + $this->removeInvite($invite); + + return $this; + } + public function addPerson(Person $person): self { $this->persons[] = $person; @@ -309,14 +332,12 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface return $this->getProfessionals(); } - public function getUser(): ?User + /** + * @return Collection|User[] + */ + public function getUsers(): Collection { - return $this->user; - } - - public function getusers(): Collection - { - return $this->getInvites(); //TODO get users of the invite + return $this->getInvites()->map(function (Invite $i) { return $i->getUser(); }); } public static function loadValidatorMetadata(ClassMetadata $metadata): void @@ -335,7 +356,9 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface public function removeInvite(Invite $invite): self { - $this->invites->removeElement($invite); + if ($this->invites->removeElement($invite)) { + $invite->setCalendar(null); + } return $this; } diff --git a/src/Bundle/ChillCalendarBundle/Entity/Invite.php b/src/Bundle/ChillCalendarBundle/Entity/Invite.php index fac0a833b..96713ed2a 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Invite.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Invite.php @@ -40,14 +40,14 @@ class Invite implements TrackUpdateInterface, TrackCreationInterface /** * @ORM\ManyToOne(targetEntity=Calendar::class, inversedBy="invites") */ - private ?Calendar $calendar; + private ?Calendar $calendar = null; /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ - private ?int $id; + private ?int $id = null; /** * @ORM\Column(type="text", nullable=false, options={"default": "pending"}) @@ -58,7 +58,7 @@ class Invite implements TrackUpdateInterface, TrackCreationInterface * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") * @ORM\JoinColumn(nullable=false) */ - private ?User $user; + private ?User $user = null; public function getCalendar(): ?Calendar { @@ -82,8 +82,6 @@ class Invite implements TrackUpdateInterface, TrackCreationInterface /** * @internal use Calendar::addInvite instead - * @param Calendar|null $calendar - * @return void */ public function setCalendar(?Calendar $calendar): void { @@ -99,6 +97,10 @@ class Invite implements TrackUpdateInterface, TrackCreationInterface public function setUser(?User $user): self { + if ($user instanceof User && $this->user instanceof User && $user !== $this->user) { + throw new \LogicException("Not allowed to associate an invite to a different user"); + } + $this->user = $user; return $this; diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 74ad6343a..35f0b5075 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -70,6 +70,7 @@ class CalendarType extends AbstractType if ($options['data'] instanceof Calendar && $options['data']->getId() === null) { $builder->add('mainUser', PickUserDynamicType::class, [ + 'multiple' => false, 'required' => true, 'help' => 'chill_calendar.form.The main user is mandatory. He will organize the appointment.', ]); @@ -192,26 +193,6 @@ class CalendarType extends AbstractType return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]); } )); - - $builder->add('invites', HiddenType::class); - $builder->get('invites') - ->addModelTransformer(new CallbackTransformer( - static function (iterable $usersAsIterable): string { - $userIds = []; - - foreach ($usersAsIterable as $value) { - $userIds[] = $value->getId(); - } - - return implode(',', $userIds); - }, - function (?string $usersAsString): array { - return array_map( - fn (string $id): ?Invite => $this->om->getRepository(Invite::class)->findOneBy(['id' => (int) $id]), - explode(',', $usersAsString) - ); - } - )); } public function configureOptions(OptionsResolver $resolver) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index a0d5a8715..408d68147 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -180,8 +180,8 @@ const store = createStore({ startDateInput.value = payload.startStr; let endDateInput = document.getElementById("chill_activitybundle_activity_endDate"); endDateInput.value = payload.endStr; - let mainUserInput = document.getElementById("chill_activitybundle_activity_mainUser"); - mainUserInput.value = payload.users.logged.id; + //let mainUserInput = document.getElementById("chill_activitybundle_activity_mainUser"); + //mainUserInput.value = payload.users.logged.id; commit('setEvents', payload); }, updateEvent({ commit }, payload) { @@ -192,8 +192,8 @@ const store = createStore({ endDateInput.value = payload.event.end.toISOString(); let calendarRangeInput = document.getElementById("chill_activitybundle_activity_calendarRange"); calendarRangeInput.value = Number(payload.event.extendedProps.calendarRangeId); - let mainUserInput = document.getElementById("chill_activitybundle_activity_mainUser"); - mainUserInput.value = Number(payload.event.source.id); + //let mainUserInput = document.getElementById("chill_activitybundle_activity_mainUser"); + //mainUserInput.value = Number(payload.event.source.id); commit('setEvents', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Tests/Entity/CalendarTest.php b/src/Bundle/ChillCalendarBundle/Tests/Entity/CalendarTest.php new file mode 100644 index 000000000..c6d7b73a7 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Tests/Entity/CalendarTest.php @@ -0,0 +1,44 @@ +assertCount(0, $calendar->getInvites()); + $this->assertCount(0, $calendar->getUsers()); + + $calendar->addUser($user0 = new User()); + + $this->assertCount(1, $calendar->getInvites()); + $this->assertCount(1, $calendar->getUsers()); + $this->assertSame($user0, $calendar->getUsers()->first()); + + $calendar->addUser($user1 = new User()); + + $this->assertCount(2, $calendar->getInvites()); + $this->assertCount(2, $calendar->getUsers()); + $this->assertContains($user0, $calendar->getUsers()); + $this->assertContains($user1, $calendar->getUsers()); + + $calendar->removeUser($user0); + + $this->assertCount(1, $calendar->getInvites()); + $this->assertCount(1, $calendar->getUsers()); + $this->assertNotSame($user0, $calendar->getUsers()->first()); + $this->assertSame($user1, $calendar->getUsers()->first()); + + $calendar->removeUser($user1); + + $this->assertCount(0, $calendar->getInvites()); + $this->assertCount(0, $calendar->getUsers()); + } + +} diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php index 95c447119..1795741a1 100644 --- a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/EntityToJsonTransformer.php @@ -43,6 +43,9 @@ class EntityToJsonTransformer implements DataTransformerInterface public function reverseTransform($value) { + dump($value); + dump($this->type); + dump($this->multiple); $denormalized = json_decode($value, true); if ($this->multiple) { diff --git a/src/Bundle/ChillMainBundle/Repository/LocationRepository.php b/src/Bundle/ChillMainBundle/Repository/LocationRepository.php index 253298d49..26c338d39 100644 --- a/src/Bundle/ChillMainBundle/Repository/LocationRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/LocationRepository.php @@ -13,6 +13,7 @@ namespace Chill\MainBundle\Repository; use Chill\MainBundle\Entity\Location; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\Persistence\ManagerRegistry; /** @@ -37,4 +38,18 @@ class LocationRepository extends ServiceEntityRepository { return $this->findBy(['active' => true, 'availableForUsers' => true]); } + + /** + * fetch location by name + * + * @return array|Location[] + */ + public function findByName(string $name, string $lang): array + { + $rsm = new ResultSetMappingBuilder($this->getEntityManager()); + $rsm->addRootEntityFromClassMetadata(Location::class); + + $sql = "SELECT " + + } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js index 511d2126e..4e71e8568 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js @@ -6,6 +6,7 @@ import { appMessages } from 'ChillMainAssets/vuejs/PickEntity/i18n'; const i18n = _createI18n(appMessages); let appsOnPage = new Map(); +let appsPerInput = new Map(); function loadDynamicPicker(element) { @@ -23,6 +24,8 @@ function loadDynamicPicker(element) { null : [ JSON.parse(input.value) ] ) ; + console.log('picked at startup', picked); + console.log('input', input); if (!isMultiple) { if (input.value === '[]'){ @@ -78,13 +81,14 @@ function loadDynamicPicker(element) { .mount(el); appsOnPage.set(uniqId, app); + appsPerInput.set(input.name, app); }); } document.addEventListener('show-hide-show', function(e) { loadDynamicPicker(e.detail.container) -}) +}); document.addEventListener('show-hide-hide', function(e) { console.log('hiding event caught') @@ -95,7 +99,23 @@ document.addEventListener('show-hide-hide', function(e) { appsOnPage.delete(uniqId); } }) -}) +}); + +document.addEventListener('pick-entity-type', function (e) { + console.log('pick entity event', e); + if (!appsPerInput.has(e.detail.name)) { + console.error('no app with this name'); + return; + } + const app = appsPerInput.get(e.detail.name); + if (e.detail.action === 'add') { + app.addNewEntity(e.detail.entity); + } else if (e.detail.action === 'remove') { + app.removeEntity(e.detail.entity); + } else { + console.error('action not supported: '+e.detail.action); + } +}); document.addEventListener('DOMContentLoaded', function(e) { loadDynamicPicker(document) diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig index ded9ff83d..212b4fbd2 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig @@ -231,6 +231,6 @@ {% endblock %} {% block pick_entity_dynamic_widget %} - +
{% endblock %}