Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ js_dist
drivers
chromedriver.log
/htdocs/dist
app/config/reference.php
13 changes: 13 additions & 0 deletions db/migrations/20260430000000_add_mic_type_to_speakers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

class AddMicTypeToSpeakers extends AbstractMigration
{
public function change(): void
{
$this->query("ALTER TABLE afup_conferenciers ADD mic_type ENUM('handheld', 'headset') DEFAULT NULL AFTER bluesky");
}
}
13 changes: 13 additions & 0 deletions db/migrations/20260501000000_add_mic_type_enabled_to_forum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

class AddMicTypeEnabledToForum extends AbstractMigration
{
public function change(): void
{
$this->query("ALTER TABLE afup_forum ADD mic_type_enabled TINYINT DEFAULT 0");
}
}
1 change: 1 addition & 0 deletions db/seeds/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function run(): void
'date_annonce_planning' => $now - $oneMonthInSeconds,
'transport_information_enabled' => 1,
'has_prices_defined_with_vat' => 1,
'mic_type_enabled' => 1,
],
[
'id' => 2,
Expand Down
4 changes: 4 additions & 0 deletions sources/AppBundle/Event/Form/EventType.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'label' => 'Activer les nuits d\'hôtel',
'required' => false,
])
->add('micTypeEnabled', CheckboxType::class, [
'label' => 'Activer le choix du type de microphone',
'required' => false,
])
->add('coupons', TextareaType::class, [
'mapped' => false,
'label' => 'Liste des coupons',
Expand Down
17 changes: 17 additions & 0 deletions sources/AppBundle/Event/Model/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class Event implements NotifyPropertyInterface

private ?bool $accomodationEnabled = null;

private ?bool $micTypeEnabled = null;
Comment thread
Mopolo marked this conversation as resolved.

private ?bool $transportInformationEnabled = null;

/**
Expand Down Expand Up @@ -625,6 +627,21 @@ public function setAccomodationEnabled($accomodationEnabled): self
return $this;
}

public function getMicTypeEnabled(): ?bool
{
return $this->micTypeEnabled;
}

public function setMicTypeEnabled($micTypeEnabled): self
{
$micTypeEnabled = (bool) $micTypeEnabled;

$this->propertyChanged('micTypeEnabled', $this->micTypeEnabled, $micTypeEnabled);
$this->micTypeEnabled = $micTypeEnabled;

return $this;
}

public function isAfupDay(): bool
{
return str_starts_with((string) $this->getTitle(), 'AFUP Day');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,12 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
'type' => 'bool',
'serializer' => Boolean::class,
])
->addField([
'columnName' => 'mic_type_enabled',
'fieldName' => 'micTypeEnabled',
'type' => 'bool',
'serializer' => Boolean::class,
])
->addField([
'columnName' => 'waiting_list_url',
'fieldName' => 'waitingListUrl',
Expand Down
14 changes: 13 additions & 1 deletion sources/AppBundle/Event/Model/Repository/SpeakerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
use AppBundle\Event\Model\Event;
use AppBundle\Event\Model\Speaker;
use AppBundle\Event\Model\Talk;
use AppBundle\Event\Speaker\MicrophoneType;
use AppBundle\Ting\JoinHydrator;
use CCMBenchmark\Ting\Driver\Mysqli\Serializer\Boolean;
use CCMBenchmark\Ting\Repository\CollectionInterface;
use CCMBenchmark\Ting\Repository\HydratorSingleObject;
use CCMBenchmark\Ting\Repository\Metadata;
use CCMBenchmark\Ting\Repository\MetadataInitializer;
use CCMBenchmark\Ting\Repository\Repository;
use CCMBenchmark\Ting\Serializer\BackedEnum;
use CCMBenchmark\Ting\Serializer\SerializerFactoryInterface;
use Webmozart\Assert\Assert;

Expand Down Expand Up @@ -63,7 +65,8 @@ public function getScheduledSpeakersByEvent(Event $event, $returnTalksThatWillBe
speaker.phone_number,
speaker.has_hosting_sponsor,
speaker.travel_refund_needed,
speaker.travel_refund_sponsored
speaker.travel_refund_sponsored,
speaker.mic_type
FROM afup_conferenciers speaker
INNER JOIN afup_conferenciers_sessions cs ON cs.conferencier_id = speaker.conferencier_id
INNER JOIN afup_sessions talk ON talk.session_id = cs.session_id
Expand Down Expand Up @@ -320,6 +323,15 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
'type' => 'bool',
'serializer' => Boolean::class,
])
->addField([
'columnName' => 'mic_type',
'fieldName' => 'micType',
'type' => 'enum',
'serializer' => BackedEnum::class,
'serializer_options' => [
'unserialize' => ['enum' => MicrophoneType::class],
],
])
;

return $metadata;
Expand Down
14 changes: 14 additions & 0 deletions sources/AppBundle/Event/Model/Speaker.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace AppBundle\Event\Model;

use AppBundle\Event\Speaker\MicrophoneType;
use CCMBenchmark\Ting\Entity\NotifyProperty;
use CCMBenchmark\Ting\Entity\NotifyPropertyInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
Expand Down Expand Up @@ -135,6 +136,8 @@ class Speaker implements NotifyPropertyInterface
private bool $travelRefundNeeded = true;
private bool $travelRefundSponsored = false;

private ?MicrophoneType $micType = null;

public function getId(): ?int
{
return $this->id;
Expand Down Expand Up @@ -708,6 +711,17 @@ public function setTravelRefundSponsored(bool $travelRefundSponsored): self
return $this;
}

public function getMicType(): ?MicrophoneType
{
return $this->micType;
}

public function setMicType(?MicrophoneType $micType): void
{
$this->propertyChanged('micType', $this->micType, $micType);
$this->micType = $micType;
}

public function hasHotelNightBefore(): ?bool
{
if (null === ($hotelNights = $this->getHotelNightsArray())) {
Expand Down
11 changes: 11 additions & 0 deletions sources/AppBundle/Event/Speaker/MicrophoneType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace AppBundle\Event\Speaker;

enum MicrophoneType: string
{
case Headset = 'headset';
case Handheld = 'handheld';
}
15 changes: 15 additions & 0 deletions sources/AppBundle/Event/Speaker/SpeakerPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use AppBundle\SpeakerInfos\Form\SpeakersContactType;
use AppBundle\SpeakerInfos\Form\SpeakersDinerType;
use AppBundle\SpeakerInfos\Form\SpeakersExpensesType;
use AppBundle\SpeakerInfos\Form\SpeakersMicrophoneType;
use AppBundle\SpeakerInfos\Form\TravelSponsorType;
use AppBundle\SpeakerInfos\SpeakersExpensesStorage;
use DateTime;
Expand Down Expand Up @@ -54,6 +55,18 @@ public function handleRequest(Request $request, Event $event, Speaker $speaker)
return $this->redirectFromRequest($request);
}

$shouldDisplayMicrophoneForm = (bool) $event->getMicTypeEnabled();

$speakersMicrophoneType = $this->createForm(SpeakersMicrophoneType::class, ['type' => $speaker->getMicType()]);
$speakersMicrophoneType->handleRequest($request);
if ($shouldDisplayMicrophoneForm && $speakersMicrophoneType->isSubmitted() && $speakersMicrophoneType->isValid()) {
$speaker->setMicType($speakersMicrophoneType->getData()['type']);
$this->speakerRepository->save($speaker);
$this->addFlash('notice', 'Préférence de microphone enregistrée');

return $this->redirectFromRequest($request);
}

$speakersDinerDefaults = [
'will_attend' => $speaker->getWillAttendSpeakersDiner(),
'has_special_diet' => $speaker->getHasSpecialDiet(),
Expand Down Expand Up @@ -169,6 +182,7 @@ public function handleRequest(Request $request, Event $event, Speaker $speaker)
'description' => $description,
'talks_infos' => $this->addTalkInfos($event, $talks),
'speaker' => $speaker,
'should_display_microphone_form' => $shouldDisplayMicrophoneForm,
'should_display_speakers_diner_form' => $shouldDisplaySpeakersDinerForm,
'should_display_hotel_reservation_form' => $shouldDisplayHotelReservationForm,
'speakers_expenses_form' => $speakersExpensesType->createView(),
Expand All @@ -177,6 +191,7 @@ public function handleRequest(Request $request, Event $event, Speaker $speaker)
'speakers_diner_form' => $speakersDinerType->createView(),
'hotel_reservation_form' => $hotelReservationType->createView(),
'speakers_contact_form' => $speakersContactType->createView(),
'speakers_microphone_form' => $speakersMicrophoneType->createView(),
'day_before_event' => DateTimeImmutable::createFromMutable($event->getDateStart())->modify('- 1 day'),
]);
}
Expand Down
38 changes: 38 additions & 0 deletions sources/AppBundle/SpeakerInfos/Form/SpeakersMicrophoneType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace AppBundle\SpeakerInfos\Form;

use AppBundle\Event\Speaker\MicrophoneType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SpeakersMicrophoneType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('type', EnumType::class, [
'class' => MicrophoneType::class,
'label' => 'speaker_infos.microphone.label',
'expanded' => true,
'placeholder' => 'speaker_infos.microphone.placeholder',
'choice_label' => fn(MicrophoneType $type) => match ($type) {
MicrophoneType::Headset => 'speaker_infos.microphone.choice.headset',
MicrophoneType::Handheld => 'speaker_infos.microphone.choice.handheld',
},
'choice_translation_domain' => true,
'required' => false,
])
->add('submit', SubmitType::class, ['label' => 'Enregistrer']);
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(['csrf_protection' => false]);
}
}
1 change: 1 addition & 0 deletions templates/admin/event/form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
{{ _self.wysiwyg(form.CFP.speaker_management_en) }}
{{ form_row(form.speakersDinerEnabled) }}
{{ form_row(form.accomodationEnabled) }}
{{ form_row(form.micTypeEnabled) }}
{{ form_row(form.dateEndSpeakersDinerInfosCollection) }}
{{ form_row(form.dateEndHotelInfosCollection) }}
</div>
Expand Down
14 changes: 13 additions & 1 deletion templates/admin/event/speakers_management.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<th data-tf-filter-type="select" class="center aligned">Pas de nuit d'hotel ?</th>
<th data-tf-filter-type="select" class="center aligned">Sponsors ?</th>
<th data-tf-filter-type="select" class="center aligned">Justificatifs envoyés ?</th>
<th data-tf-filter-type="select" class="center aligned">Microphone</th>
<th></th>
</tr>
</thead>
Expand Down Expand Up @@ -143,6 +144,17 @@
{% endif %}
</span>
</td>
<td class="center aligned">
<span class="ui label{% if speaker.speaker.micType is null %} red{% endif %}">
{% if speaker.speaker.micType is null %}
N/A
{% elseif speaker.speaker.micType.value == 'headset' %}
Casque
{% else %}
Main
{% endif %}
</span>
</td>
<td>
<a href="{{ path('admin_event_speaker_infos', {speaker_id: speaker.speaker.id, id: event.id }) }}"
data-position="left center"
Expand All @@ -154,7 +166,7 @@
</td>
</tr>
{% else %}
<tr><td colspan="12" style="text-align: center;">
<tr><td colspan="13" style="text-align: center;">
<div class="ui icon header">
<i class="meh outline icon"></i>
Aucune information. {% if event == null %}Essayez de changez d'évènement !{% endif %}
Expand Down
23 changes: 23 additions & 0 deletions templates/event/speaker/page.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
{% form_theme speakers_diner_form 'bootstrap_3_layout.html.twig' %}
{% form_theme hotel_reservation_form 'bootstrap_3_layout.html.twig' %}
{% form_theme travel_sponsor_form 'bootstrap_3_layout.html.twig' %}
{% form_theme speakers_microphone_form 'bootstrap_3_layout.html.twig' %}

{% block content %}

Expand Down Expand Up @@ -121,6 +122,28 @@

{{ form_end(speakers_contact_form) }}

{% if should_display_microphone_form %}
<h2><a id="microphone" href="#microphone">🎤 {% trans %}speaker_infos.microphone.title{% endtrans %}</a></h2>
<p>{% trans %}speaker_infos.microphone.intro{% endtrans %}</p>

{{ form_start(speakers_microphone_form, { attr: { class: "speakers-infos-form" }, action: '#microphone'}) }}

<div class="container">
<span>
{{ form_label(speakers_microphone_form.type) }}
</span>
<span>
{{ form_widget(speakers_microphone_form.type) }}
{{ form_errors(speakers_microphone_form.type) }}
</span>
<div class="submit-container">
{{ form_widget(speakers_microphone_form.submit, {attr: {title: "Enregistrer le choix de microphone"}}) }}
</div>
</div>

{{ form_end(speakers_microphone_form) }}
{% endif %}

{% if event.speakersDinerEnabled %}
<h2><a id="diner" href="#diner">🍽️ {% trans %}Nous vous invitons au restaurant{% endtrans %}</a></h2>

Expand Down
20 changes: 20 additions & 0 deletions tests/behat/features/EventPages/SpeakerInfos.feature
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,23 @@ Feature: Event > Profil speaker
And I press "Enregistrer le travel sponsor"
Then I should see "Informations sur vos transports enregistrées "
Then the "travel_sponsor_choices_1" checkbox should be checked

@reloadDbWithTestData
Scenario: Saisie du type de microphone - micro casque
Given I go to "/event/forum/speaker-infos"
When I follow "Connect as agallou"

When I select "headset" from "speakers_microphone[type]"
And I press "Enregistrer le choix de microphone"
Then I should see "Préférence de microphone enregistrée"
Then the "speakers_microphone_type_0" checkbox should be checked

@reloadDbWithTestData
Scenario: Saisie du type de microphone - micro à main
Given I go to "/event/forum/speaker-infos"
When I follow "Connect as agallou"

When I select "handheld" from "speakers_microphone[type]"
And I press "Enregistrer le choix de microphone"
Then I should see "Préférence de microphone enregistrée"
Then the "speakers_microphone_type_1" checkbox should be checked
6 changes: 6 additions & 0 deletions translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,9 @@ speaker_infos.hosting_sponsor.intro: "If your hosting is sponsored by your compa
speaker_infos.travel_expenses.checkbox_label.not_needed: "I don't need it"
speaker_infos.travel_expenses.checkbox_label.sponsored: "My transports costs are sponsored"
speaker_infos.sponsor.travel.intro: "Check one of these boxes if you don't need to be refunded your transports costs or if they are are sponsored by your company."
speaker_infos.microphone.title: "Microphone type"
speaker_infos.microphone.intro: "Please indicate your microphone preference for your talks. We will do our best to accommodate your choice depending on availability."
speaker_infos.microphone.label: "Microphone type"
speaker_infos.microphone.placeholder: "No preference"
speaker_infos.microphone.choice.headset: "Headset microphone"
speaker_infos.microphone.choice.handheld: "Handheld microphone"
6 changes: 6 additions & 0 deletions translations/messages.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,9 @@ speaker_infos.hosting_sponsor.intro: "Si votre hébergement est pris en charge p
speaker_infos.travel_expenses.checkbox_label.not_needed: "Je n’en n’ai pas besoin"
speaker_infos.travel_expenses.checkbox_label.sponsored: "Mon transport est sponsorisé"
speaker_infos.sponsor.travel.intro: "Cochez une de ces cases si vous n'avez pas besoin de défrayment ou si votre transport est pris en charge par votre entreprise."
speaker_infos.microphone.title: "Type de microphone"
speaker_infos.microphone.intro: "Indiquez-nous votre préférence pour le type de microphone lors de vos conférences. Nous ferons notre possible pour respecter votre choix en fonction des disponibilités."
speaker_infos.microphone.label: "Type de microphone"
speaker_infos.microphone.placeholder: "Pas de préférence"
speaker_infos.microphone.choice.headset: "Micro casque"
speaker_infos.microphone.choice.handheld: "Micro à main"
Loading