mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-03 07:26:12 +00:00
Create internal and external animators
This commit is contained in:
parent
495a43a6cd
commit
0164c57eb4
@ -204,7 +204,7 @@ final class EventController extends AbstractController
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans('The event was created'));
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', ['event_id' => $entity->getId()]);
|
||||
return $this->redirectToRoute('chill_event__event_show', ['id' => $entity->getId()]);
|
||||
}
|
||||
|
||||
$entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
|
||||
@ -310,7 +310,7 @@ final class EventController extends AbstractController
|
||||
|
||||
$this->addFlash('success', $this->translator->trans('The event was updated'));
|
||||
|
||||
return $this->redirectToRoute('chill_event__event_show', ['event_id' => $event_id]);
|
||||
return $this->redirectToRoute('chill_event__event_show', ['id' => $event_id]);
|
||||
}
|
||||
|
||||
return $this->render('@ChillEvent/Event/edit.html.twig', [
|
||||
|
@ -1,127 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\EventBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* Represents an animator that can be either a User or a ThirdParty.
|
||||
*/
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'chill_event_animator')]
|
||||
#[Assert\Expression(
|
||||
'this.getUser() !== null or this.getThirdparty() !== null',
|
||||
message: 'An animator must be either a User or a ThirdParty'
|
||||
)]
|
||||
class Animator
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::INTEGER)]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ThirdParty::class)]
|
||||
#[ORM\JoinColumn(name: 'thirdparty_id', referencedColumnName: 'id', nullable: true)]
|
||||
#[Serializer\Groups(['read'])]
|
||||
private ?ThirdParty $thirdparty = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: User::class)]
|
||||
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true)]
|
||||
#[Serializer\Groups(['read'])]
|
||||
private ?User $user = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Event::class, inversedBy: 'animators')]
|
||||
#[ORM\JoinColumn(name: 'event_id', referencedColumnName: 'id', nullable: false)]
|
||||
private ?Event $event = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getThirdparty(): ?ThirdParty
|
||||
{
|
||||
return $this->thirdparty;
|
||||
}
|
||||
|
||||
public function setThirdparty(?ThirdParty $thirdparty): self
|
||||
{
|
||||
$this->thirdparty = $thirdparty;
|
||||
|
||||
if (null !== $thirdparty) {
|
||||
$this->user = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?User $user): self
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
if (null !== $user) {
|
||||
$this->thirdparty = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEvent(): ?Event
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
public function setEvent(?Event $event): self
|
||||
{
|
||||
$this->event = $event;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAnimator(): User|ThirdParty|null
|
||||
{
|
||||
return $this->user ?? $this->thirdparty;
|
||||
}
|
||||
|
||||
public function setAnimator(User|ThirdParty|null $animator): self
|
||||
{
|
||||
if ($animator instanceof User) {
|
||||
$this->setUser($animator);
|
||||
} elseif ($animator instanceof ThirdParty) {
|
||||
$this->setThirdparty($animator);
|
||||
} else {
|
||||
$this->user = null;
|
||||
$this->thirdparty = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isUser(): bool
|
||||
{
|
||||
return null !== $this->user;
|
||||
}
|
||||
|
||||
public function isThirdParty(): bool
|
||||
{
|
||||
return null !== $this->thirdparty;
|
||||
}
|
||||
}
|
@ -63,13 +63,17 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
|
||||
/**
|
||||
* @var Collection<int, User>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'event', targetEntity: User::class)]
|
||||
#[ORM\ManyToMany(targetEntity: User::class)]
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\JoinTable('chill_event_animatorsintern')]
|
||||
private Collection $animatorsIntern;
|
||||
|
||||
/**
|
||||
* @var Collection<int, ThirdParty>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'event', targetEntity: ThirdParty::class)]
|
||||
#[ORM\ManyToMany(targetEntity: ThirdParty::class)]
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\JoinTable('chill_event_animatorsextern')]
|
||||
private Collection $animatorsExtern;
|
||||
|
||||
#[Assert\NotBlank]
|
||||
@ -204,26 +208,26 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
|
||||
return $this->animatorsExtern;
|
||||
}
|
||||
|
||||
public function addAnimatorIntern(User $ai): self
|
||||
public function addAnimatorsIntern(User $ai): self
|
||||
{
|
||||
$this->animatorsIntern->add($ai);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeAnimatorIntern(User $ai): void
|
||||
public function removeAnimatorsIntern(User $ai): void
|
||||
{
|
||||
$this->animatorsIntern->removeElement($ai);
|
||||
}
|
||||
|
||||
public function addAnimatorExtern(User $ae): self
|
||||
public function addAnimatorsExtern(ThirdParty $ae): self
|
||||
{
|
||||
$this->animatorsExtern->add($ae);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeAnimatorExtern(User $ae): void
|
||||
public function removeAnimatorsExtern(ThirdParty $ae): void
|
||||
{
|
||||
$this->animatorsExtern->removeElement($ae);
|
||||
}
|
||||
|
@ -32,12 +32,14 @@ use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class EventType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private readonly IdToLocationDataTransformer $idToLocationDataTransformer,
|
||||
private readonly EventBudgetKindRepository $eventBudgetKindRepository,
|
||||
private readonly TranslatorInterface $translator,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
@ -70,12 +72,12 @@ class EventType extends AbstractType
|
||||
])
|
||||
->add('animatorsIntern', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'label' => 'Pick an internal animator',
|
||||
'label' => $this->translator->trans('event.fields.internal animators'),
|
||||
'required' => false,
|
||||
])
|
||||
->add('animatorsExtern', PickThirdpartyDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'label' => 'Pick an external animator',
|
||||
'label' => $this->translator->trans('event.fields.external animators'),
|
||||
'required' => false,
|
||||
])
|
||||
->add('budgetElements', ChillCollectionType::class, [
|
||||
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\EventBundle\Form\Type;
|
||||
|
||||
use Chill\EventBundle\Form\DataTransformer\AnimatorCollectionTransformer;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class PickAnimatorType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->add('thirdparty', PickThirdpartyDynamicType::class, [
|
||||
'required' => false,
|
||||
])
|
||||
->add('user', PickUserDynamicType::class, [
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
// Add the data transformer
|
||||
// $builder->addModelTransformer(new AnimatorCollectionTransformer($this->entityManager));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => null,
|
||||
'multiple' => false,
|
||||
'placeholder' => 'Select an animator...',
|
||||
'required' => false,
|
||||
'by_reference' => false,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('multiple', 'bool');
|
||||
$resolver->setAllowedTypes('placeholder', ['string', 'null']);
|
||||
}
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
{{ form_row(edit_form.type, { label: "Event type" }) }}
|
||||
{{ form_row(edit_form.themes) }}
|
||||
{{ form_row(edit_form.moderator) }}
|
||||
{{ form_row(edit_form.animators) }}
|
||||
{{ form_row(edit_form.animatorsIntern) }}
|
||||
{{ form_row(edit_form.animatorsExtern) }}
|
||||
{{ form_row(edit_form.location) }}
|
||||
{{ form_row(edit_form.budgetElements) }}
|
||||
{{ form_row(edit_form.comment) }}
|
||||
|
@ -11,7 +11,7 @@ block js %}
|
||||
|
||||
{{ filter | chill_render_filter_order_helper }}
|
||||
|
||||
{# {% if is_granted('CHILL_EVENT_CREATE') %} #}
|
||||
{% if is_granted('CHILL_EVENT_CREATE') %}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a
|
||||
@ -25,7 +25,9 @@ block js %}
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
{# {% endif %} #} {% if events|length > 0 %}
|
||||
{% endif %}
|
||||
|
||||
{% if events|length > 0 %}
|
||||
<div class="flex-table">
|
||||
{% for e in events %}
|
||||
<div class="item-bloc">
|
||||
@ -41,6 +43,7 @@ block js %}
|
||||
{{ e.moderator | chill_entity_render_box }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% for t in e.themes %}
|
||||
<span>{{ t|chill_entity_render_box }}</span>
|
||||
@ -53,6 +56,7 @@ block js %}
|
||||
<p>
|
||||
{{ 'count participations to this event'|trans({'count': e.participations|length}) }}
|
||||
</p>
|
||||
<p>{{ "center"|trans }}: {{ e.center.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,9 +65,17 @@
|
||||
<td>{{ event.moderator|chill_entity_render_string }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'Animators'|trans }}</th>
|
||||
<th>{{ 'event.animators.intern'|trans }}</th>
|
||||
<td>
|
||||
{% for a in event.animators %}
|
||||
{% for a in event.animatorsIntern %}
|
||||
{{ _self.insert_onthefly('user', a) }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'event.animators.extern'|trans }}</th>
|
||||
<td>
|
||||
{% for a in event.animatorsExtern %}
|
||||
{{ _self.insert_onthefly('thirdparty', a) }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
@ -153,7 +161,7 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="chill-no-data-statement">{{ 'event.budget.no elements' }}</p>
|
||||
<p class="chill-no-data-statement">{{ 'event.budget.no elements'|trans }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -180,7 +188,7 @@
|
||||
<div class="participations-wrapper">
|
||||
<h2>{{ 'Participations'|trans }}</h2>
|
||||
{% set count = event.participations|length %}
|
||||
<p>{{ 'count participations to this event'|trans({'count': count}) }}</p>
|
||||
<p class="chill-no-data-statement">{{ 'count participations to this event'|trans({'count': count}) }}</p>
|
||||
|
||||
{% if count > 0 %}
|
||||
<table class="table table-bordered border-dark align-middle">
|
||||
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Event;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20250702144312 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add internal and external animators to event entity';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE TABLE chill_event_animatorsintern (event_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(event_id, user_id))
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE INDEX IDX_E699558771F7E88B ON chill_event_animatorsintern (event_id)
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE INDEX IDX_E6995587A76ED395 ON chill_event_animatorsintern (user_id)
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE TABLE chill_event_animatorsextern (event_id INT NOT NULL, thirdparty_id INT NOT NULL, PRIMARY KEY(event_id, thirdparty_id))
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE INDEX IDX_7EFBF7DE71F7E88B ON chill_event_animatorsextern (event_id)
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
CREATE INDEX IDX_7EFBF7DEC7D3A8E6 ON chill_event_animatorsextern (thirdparty_id)
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsintern ADD CONSTRAINT FK_E699558771F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsintern ADD CONSTRAINT FK_E6995587A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsextern ADD CONSTRAINT FK_7EFBF7DE71F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsextern ADD CONSTRAINT FK_7EFBF7DEC7D3A8E6 FOREIGN KEY (thirdparty_id) REFERENCES chill_3party.third_party (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsintern DROP CONSTRAINT FK_E699558771F7E88B
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsintern DROP CONSTRAINT FK_E6995587A76ED395
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsextern DROP CONSTRAINT FK_7EFBF7DE71F7E88B
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
ALTER TABLE chill_event_animatorsextern DROP CONSTRAINT FK_7EFBF7DEC7D3A8E6
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
DROP TABLE chill_event_animatorsintern
|
||||
SQL);
|
||||
$this->addSql(<<<'SQL'
|
||||
DROP TABLE chill_event_animatorsextern
|
||||
SQL);
|
||||
}
|
||||
}
|
@ -141,6 +141,8 @@ event:
|
||||
organizationCost: Coût d'organisation
|
||||
location: Localisation
|
||||
documents: Documents
|
||||
internal animators: Animateurs internes
|
||||
external animators: Animateurs externes
|
||||
form:
|
||||
organisationCost_help: Coût d'organisation pour la structure. Utile pour les statistiques.
|
||||
add_document: Ajouter un document
|
||||
@ -159,6 +161,9 @@ event:
|
||||
charge type: Charge
|
||||
amount: Montant
|
||||
comment: Commentaire
|
||||
animators:
|
||||
intern: Animateurs internes
|
||||
extern: Animateurs externes
|
||||
|
||||
crud:
|
||||
event_theme:
|
||||
|
Loading…
x
Reference in New Issue
Block a user