diff --git a/src/Controller/Administrative/SeasonAssignment/TaskDeadlineController.php b/src/Controller/Administrative/SeasonAssignment/TaskDeadlineController.php index 7142a6e..d3c31db 100644 --- a/src/Controller/Administrative/SeasonAssignment/TaskDeadlineController.php +++ b/src/Controller/Administrative/SeasonAssignment/TaskDeadlineController.php @@ -46,6 +46,9 @@ class TaskDeadlineController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { + $applyToAll = true === $form->get('applyToAll')->getData(); + $appliedCount = $applyToAll ? ($seasonAssignment?->applyDeadlinesToOpenTasks($task) ?? 0) : 0; + $this->entityManager->flush(); $this->logger->info('Change season assignment task deadlines', [ @@ -54,9 +57,13 @@ class TaskDeadlineController extends AbstractController 'task' => $task->getTaskKey(), 'deadline_override_1' => $task->getDeadlineOverride1()?->format('Y-m-d'), 'deadline_override_2' => $task->getDeadlineOverride2()?->format('Y-m-d'), + 'apply_to_all' => $applyToAll, + 'applied_count' => $appliedCount, ]); - $this->addFlash('success', 'Die Fristen wurden gespeichert'); + $this->addFlash('success', $applyToAll + ? 'Die Fristen wurden für alle offenen Einträge gespeichert' + : 'Die Fristen wurden gespeichert'); return new HxRedirectResponse($returnUrl); } diff --git a/src/Entity/SeasonAssignment.php b/src/Entity/SeasonAssignment.php index 97d9b41..29976b1 100644 --- a/src/Entity/SeasonAssignment.php +++ b/src/Entity/SeasonAssignment.php @@ -208,6 +208,30 @@ class SeasonAssignment implements BlameableEntityInterface, TimestampableEntityI return $this; } + /** + * Copies both deadline overrides of $source onto every other entry that is not ticked off, + * empty ones included - an empty override resets the entry to its computed deadline. Entries + * already done keep theirs: their deadline is history by then. + * + * @return int the number of entries changed, $source not counted + */ + public function applyDeadlinesToOpenTasks(SeasonAssignmentTask $source): int + { + $count = 0; + + foreach ($this->tasks as $task) { + if ($task === $source || $task->isDone()) { + continue; + } + + $task->setDeadlineOverride1($source->getDeadlineOverride1()); + $task->setDeadlineOverride2($source->getDeadlineOverride2()); + ++$count; + } + + return $count; + } + /** * @return Collection */ diff --git a/src/Form/SeasonTaskDeadlineType.php b/src/Form/SeasonTaskDeadlineType.php index 58e6a6b..deff894 100644 --- a/src/Form/SeasonTaskDeadlineType.php +++ b/src/Form/SeasonTaskDeadlineType.php @@ -4,6 +4,7 @@ namespace App\Form; use App\Entity\SeasonAssignmentTask; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -27,6 +28,13 @@ class SeasonTaskDeadlineType extends AbstractType 'required' => false, 'help' => 'Ohne Angabe gilt Frist 1.', ]) + // unmapped: the controller copies the entered deadlines onto the other entries + ->add('applyToAll', CheckboxType::class, [ + 'label' => 'auf alle Fristen anwenden', + 'required' => false, + 'mapped' => false, + 'help' => 'Gilt für alle noch nicht erledigten Einträge. Leere Felder setzen deren Fristen auf den berechneten Wert zurück.', + ]) ; } diff --git a/templates/administrative/season_assignment/modal_task_deadline.html.twig b/templates/administrative/season_assignment/modal_task_deadline.html.twig index 31c2739..4a15abc 100644 --- a/templates/administrative/season_assignment/modal_task_deadline.html.twig +++ b/templates/administrative/season_assignment/modal_task_deadline.html.twig @@ -10,6 +10,7 @@

{{ form_row(form.deadlineOverride1) }} {{ form_row(form.deadlineOverride2) }} + {{ form_row(form.applyToAll) }}