feat: all-season assignments
This commit is contained in:
1 parent
675cec1b69
commit
cf876ed224
119 files changed
+6194
-294
No files matched your search
@@ -122,13 +122,9 @@ class AssignmentType extends AbstractType
|
||||
;
|
||||
},
|
||||
])
|
||||
->add('remarks', TextareaType::class, [
|
||||
->add('remarks', AutosizeTextareaType::class, [
|
||||
'label' => 'Anmerkungen intern',
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
])
|
||||
->add('pickup', ChoiceType::class, [
|
||||
'label' => 'Busbegleitung ab',
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* A textarea that grows with its content, wiring up assets/controllers/textarea_autosize_controller.js.
|
||||
*
|
||||
* The controller overwrites the rows attribute on connect, so `rows` never had an effect on
|
||||
* these fields - `min_rows` is the floor it actually reads.
|
||||
*/
|
||||
class AutosizeTextareaType extends AbstractType
|
||||
{
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(['min_rows' => 1]);
|
||||
$resolver->setAllowedTypes('min_rows', 'int');
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
// Merged rather than set, and the caller's own attributes win: a field that needs a
|
||||
// second Stimulus controller on the same element composes the data-controller list
|
||||
// itself, which is the only case this can collide on.
|
||||
$view->vars['attr'] = array_merge([
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
'data-textarea-autosize-min-rows-value' => $options['min_rows'],
|
||||
], $view->vars['attr']);
|
||||
}
|
||||
|
||||
public function getParent(): string
|
||||
{
|
||||
return TextareaType::class;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ namespace App\Form;
|
||||
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
@@ -14,23 +13,15 @@ class DisableUserType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('disabledReason', TextareaType::class, [
|
||||
->add('disabledReason', AutosizeTextareaType::class, [
|
||||
'label' => 'Begründung',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
'constraints' => [
|
||||
new NotBlank(message: 'Bitte gib die Begründung ein'),
|
||||
],
|
||||
])
|
||||
->add('disabledReasonInternal', TextareaType::class, [
|
||||
->add('disabledReasonInternal', AutosizeTextareaType::class, [
|
||||
'label' => 'Begründung intern',
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Entity\Disposition;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
@@ -23,12 +22,8 @@ class DispositionCallOffType extends AbstractType
|
||||
'E&P' => Disposition::CALLED_OFF_BY_OFFICE,
|
||||
],
|
||||
])
|
||||
->add('calledOffReason', TextareaType::class, [
|
||||
->add('calledOffReason', AutosizeTextareaType::class, [
|
||||
'label' => 'Begründung',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
'constraints' => [
|
||||
new NotBlank(message: 'Bitte gib die Begründung ein'),
|
||||
],
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Config\EmailTextDefinition;
|
||||
use App\Entity\EmailText;
|
||||
use App\Validator\KnownPlaceholders;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@@ -31,13 +30,9 @@ class EmailTextType extends AbstractType
|
||||
'required' => false,
|
||||
'constraints' => [$placeholders],
|
||||
])
|
||||
->add('body', TextareaType::class, [
|
||||
->add('body', AutosizeTextareaType::class, [
|
||||
'label' => 'Text',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
'data-textarea-autosize-min-rows-value' => 12,
|
||||
],
|
||||
'min_rows' => 12,
|
||||
'constraints' => [$placeholders],
|
||||
])
|
||||
;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Config\HouseCatalog;
|
||||
use App\Entity\JobProfile;
|
||||
use App\Model\SeasonAssignmentFilterDto;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class SeasonAssignmentFilterType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly HouseCatalog $houseCatalog)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('teamerName', TextType::class, [
|
||||
'label' => 'Name',
|
||||
'required' => false,
|
||||
])
|
||||
// By code, not by name as the destination filters do: a season assignment stores
|
||||
// the code itself, so this is an exact match rather than a substring guess.
|
||||
->add('hotelCodes', MultiselectType::class, [
|
||||
'label' => 'Haus',
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choices' => $this->houseCatalog->getCodeChoices(),
|
||||
])
|
||||
->add('jobProfiles', MultiselectEntityType::class, [
|
||||
'label' => 'Job-Profile',
|
||||
'class' => JobProfile::class,
|
||||
'required' => false,
|
||||
'choice_label' => 'name',
|
||||
'empty_label' => 'nicht filtern',
|
||||
'query_builder' => function (EntityRepository $repository) {
|
||||
return $repository->createQueryBuilder('job_profile')
|
||||
->orderBy('job_profile.name', \SortDirection::Ascending);
|
||||
},
|
||||
])
|
||||
->add('includeDeleted', CheckboxType::class, [
|
||||
'label' => 'gelöschte Saisoneinsätze anzeigen',
|
||||
'required' => false,
|
||||
])
|
||||
// AbstractFilterHandler::handleRequest() branches on exactly these two names
|
||||
->add('apply', SubmitType::class, [
|
||||
'label' => 'filtern',
|
||||
])
|
||||
->add('reset', SubmitType::class, [
|
||||
'label' => 'reset',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver
|
||||
->setDefaults([
|
||||
'data_class' => SeasonAssignmentFilterDto::class,
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Config\HouseCatalog;
|
||||
use App\Entity\JobProfile;
|
||||
use App\Entity\SeasonAssignment;
|
||||
use App\Entity\Teamer;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class SeasonAssignmentType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly HouseCatalog $houseCatalog)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
// Optional: assignments are laid out first and staffed later. The endpoint only
|
||||
// ever answers with all-season teamers, so a short term teamer cannot be picked
|
||||
// here even by typing their full name.
|
||||
->add('teamer', AutocompleteEntityType::class, [
|
||||
'label' => 'Teamer:in',
|
||||
'class' => Teamer::class,
|
||||
'required' => false,
|
||||
'placeholder' => 'noch nicht zugewiesen',
|
||||
'label_property' => 'fullName',
|
||||
'label_function' => fn (Teamer $teamer) => (string) $teamer,
|
||||
'endpoint_route' => 'app_admin_autocomplete_season_teamer',
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Datum von',
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Datum bis',
|
||||
])
|
||||
// The houses map is the whole list of places an all-season teamer can be placed, so
|
||||
// a plain select over it needs neither an autocomplete endpoint nor a BusPro call.
|
||||
->add('hotelCode', ChoiceType::class, [
|
||||
'label' => 'Haus',
|
||||
'placeholder' => 'Bitte auswählen',
|
||||
'choices' => $this->houseCatalog->getCodeChoices(),
|
||||
])
|
||||
->add('jobProfile', EntityType::class, [
|
||||
'label' => 'Jobprofil',
|
||||
'class' => JobProfile::class,
|
||||
'choice_label' => 'name',
|
||||
'placeholder' => 'Bitte auswählen',
|
||||
'query_builder' => function (EntityRepository $repository) {
|
||||
return $repository->createQueryBuilder('job_profile')
|
||||
->where('job_profile.deletedAt IS NULL')
|
||||
->orderBy('job_profile.name', \SortDirection::Ascending);
|
||||
},
|
||||
])
|
||||
->add('remarks', AutosizeTextareaType::class, [
|
||||
'label' => 'Anmerkungen intern',
|
||||
'required' => false,
|
||||
'min_rows' => 4,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver
|
||||
->setDefaults([
|
||||
'data_class' => SeasonAssignment::class,
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\SeasonAssignmentTask;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* The two deadline overrides of one checklist entry.
|
||||
*
|
||||
* Both are optional: an empty field means "not overridden", and the deadline falls back to what
|
||||
* App\Service\Season\SeasonTaskDeadlineResolver computes from the destination's travel start.
|
||||
*/
|
||||
class SeasonTaskDeadlineType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('deadlineOverride1', DatepickerType::class, [
|
||||
'label' => 'Frist 1',
|
||||
'required' => false,
|
||||
])
|
||||
->add('deadlineOverride2', DatepickerType::class, [
|
||||
'label' => 'Frist 2',
|
||||
'required' => false,
|
||||
'help' => 'Ohne Angabe gilt Frist 1.',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => SeasonAssignmentTask::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\SeasonTaskDocument;
|
||||
use App\Entity\Upload;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class SeasonTaskDocumentType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('document', AutocompleteEntityType::class, [
|
||||
'label' => 'Dokument',
|
||||
'class' => Upload::class,
|
||||
'label_property' => 'originalFilename',
|
||||
'label_function' => fn (Upload $upload) => $upload->getDisplayName() ?? $upload->getOriginalFilename(),
|
||||
'endpoint_route' => 'app_admin_autocomplete_document',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => SeasonTaskDocument::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ namespace App\Form;
|
||||
|
||||
use App\Entity\Disposition;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@@ -12,13 +11,9 @@ class SpecialAgreementsType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->add('specialAgreements', TextareaType::class, [
|
||||
$builder->add('specialAgreements', AutosizeTextareaType::class, [
|
||||
'label' => 'zusätzliche Absprache',
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Form;
|
||||
|
||||
use App\Model\TeamerMailingDto;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -17,13 +16,9 @@ class TeamerMailingType extends AbstractType
|
||||
->add('subject', TextType::class, [
|
||||
'label' => 'Betreff',
|
||||
])
|
||||
->add('message', TextareaType::class, [
|
||||
->add('message', AutosizeTextareaType::class, [
|
||||
'label' => 'Nachricht',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
'data-textarea-autosize-min-rows-value' => 12,
|
||||
],
|
||||
'min_rows' => 12,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
+2
-11
@@ -5,7 +5,6 @@ namespace App\Form;
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
@@ -30,23 +29,15 @@ class UserType extends AbstractType
|
||||
'required' => false,
|
||||
'help' => 'Gesperrte Benutzer:innen können sich nicht anmelden.',
|
||||
])
|
||||
->add('disabledReason', TextareaType::class, [
|
||||
->add('disabledReason', AutosizeTextareaType::class, [
|
||||
'label' => 'Begründung',
|
||||
'required' => false,
|
||||
'help' => 'Wird bei der Anmeldung angezeigt.',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
])
|
||||
->add('disabledReasonInternal', TextareaType::class, [
|
||||
->add('disabledReasonInternal', AutosizeTextareaType::class, [
|
||||
'label' => 'Begründung intern',
|
||||
'required' => false,
|
||||
'help' => 'Wird der Benutzer:in nicht angezeigt.',
|
||||
'attr' => [
|
||||
'data-controller' => 'textarea-autosize',
|
||||
'data-action' => 'textarea-autosize#resize',
|
||||
],
|
||||
])
|
||||
;
|
||||
|
||||
|
||||
Reference in new issue
Block a user