mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-03-06 04:44:19 +01:00
Refactor translations to XLIFF format, enhance elimination workflows, and update compose configuration
This commit switches translations from YAML to XLIFF format for better standardization, updates the elimination preparation process with UI and functionality improvements, tweaks form structures, adjusts compose.override.yaml for improved asset handling, and optimizes back office usability with refined translation handling.
This commit is contained in:
@@ -31,7 +31,7 @@ class ClaimSeasonCommand extends Command
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument('email', InputArgument::REQUIRED, 'The email of the user to make admin')
|
||||
->addArgument('email', InputArgument::REQUIRED, 'The email of the user thats claims the season')
|
||||
->addArgument('season', InputArgument::REQUIRED, 'The season to claim')
|
||||
;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
namespace App\Controller\Backoffice;
|
||||
|
||||
use App\Entity\Elimination;
|
||||
use App\Entity\Quiz;
|
||||
@@ -31,6 +31,9 @@ final class PrepareEliminationController extends AbstractController
|
||||
$elimination->updateFromInputBag($request->request);
|
||||
$em->flush();
|
||||
|
||||
if (true === $request->request->getBoolean('start')) {
|
||||
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]);
|
||||
}
|
||||
$this->addFlash('success', 'Elimination updated');
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ declare(strict_types=1);
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Candidate;
|
||||
use App\Entity\Season;
|
||||
use App\Entity\Elimination;
|
||||
use App\Enum\FlashType;
|
||||
use App\Form\EliminationEnterNameType;
|
||||
use App\Helpers\Base64;
|
||||
use App\Repository\CandidateRepository;
|
||||
use App\Security\Voter\SeasonVoter;
|
||||
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
@@ -25,30 +27,50 @@ final class EliminationController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
#[Route('/elimination/{seasonCode}', name: 'app_elimination')]
|
||||
#[IsGranted(SeasonVoter::ELIMINATION, 'season')]
|
||||
public function index(#[MapEntity] Season $season): Response
|
||||
#[Route('/elimination/{elimination}', name: 'app_elimination')]
|
||||
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
||||
public function index(#[MapEntity] Elimination $elimination, Request $request): Response
|
||||
{
|
||||
return $this->render('elimination/index.html.twig', [
|
||||
$form = $this->createForm(EliminationEnterNameType::class);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$name = $form->get('name')->getData();
|
||||
|
||||
return $this->redirectToRoute('app_elimination_candidate', ['elimination' => $elimination->getId(), 'candidateHash' => Base64::base64UrlEncode($name)]);
|
||||
}
|
||||
|
||||
return $this->render('quiz/elimination/index.html.twig', [
|
||||
'form' => $form,
|
||||
'controller_name' => 'EliminationController',
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/elimination/{seasonCode}/{candidateHash}', name: 'app_elimination_cadidate')]
|
||||
#[IsGranted(SeasonVoter::ELIMINATION, 'season')]
|
||||
public function candidateScreen(Season $season, string $candidateHash, CandidateRepository $candidateRepository): Response
|
||||
#[Route('/elimination/{elimination}/{candidateHash}', name: 'app_elimination_candidate')]
|
||||
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
||||
public function candidateScreen(Elimination $elimination, string $candidateHash, CandidateRepository $candidateRepository): Response
|
||||
{
|
||||
$candidate = $candidateRepository->getCandidateByHash($season, $candidateHash);
|
||||
$candidate = $candidateRepository->getCandidateByHash($elimination->getQuiz()->getSeason(), $candidateHash);
|
||||
if (!$candidate instanceof Candidate) {
|
||||
$this->addFlash(FlashType::Warning,
|
||||
t('Cound not find candidate with name %name%', ['%name%' => Base64::base64UrlDecode($candidateHash)])->trans($this->translator)
|
||||
);
|
||||
throw new \InvalidArgumentException('Candidate not found');
|
||||
|
||||
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]);
|
||||
}
|
||||
|
||||
return $this->render('elimination/candidate.html.twig', [
|
||||
'season' => $season,
|
||||
$screenColour = $elimination->getScreenColour($candidate->getName());
|
||||
|
||||
if (null === $screenColour) {
|
||||
$this->addFlash(FlashType::Warning, $this->translator->trans('Cound not find candidate with name %name% in elimination.', ['%name%' => $candidate->getName()]));
|
||||
|
||||
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]);
|
||||
}
|
||||
|
||||
return $this->render('quiz/elimination/candidate.html.twig', [
|
||||
'candidate' => $candidate,
|
||||
'colour' => $screenColour,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,11 @@ class Elimination
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenColour(?string $name): ?string
|
||||
{
|
||||
return $this->data[$name] ?? null;
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
|
||||
30
src/Form/EliminationEnterNameType.php
Normal file
30
src/Form/EliminationEnterNameType.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/** @extends AbstractType<null> */
|
||||
class EliminationEnterNameType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('name', TextType::class,
|
||||
[
|
||||
'required' => true,
|
||||
'label' => $this->translator->trans('Enter name'),
|
||||
'translation_domain' => false,
|
||||
'attr' => ['autofocus' => true],
|
||||
],
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ class EnterNameType extends AbstractType
|
||||
'required' => true,
|
||||
'label' => $this->translator->trans('Enter your name'),
|
||||
'translation_domain' => false,
|
||||
'attr' => ['autofocus' => true],
|
||||
],
|
||||
)
|
||||
;
|
||||
|
||||
@@ -19,10 +19,13 @@ class SelectSeasonType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('season_code', TextType::class,
|
||||
['required' => true, 'constraints' => new Regex(pattern: "/^[A-Za-z\d]{5}$/"), 'label' => $this->translator->trans('Season Code'), 'translation_domain' => false]
|
||||
)
|
||||
;
|
||||
->add('season_code', TextType::class, [
|
||||
'required' => true,
|
||||
'constraints' => new Regex(pattern: "/^[A-Za-z\d]{5}$/"),
|
||||
'label' => $this->translator->trans('Season Code'),
|
||||
'translation_domain' => false,
|
||||
'attr' => ['autofocus' => true],
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\Elimination;
|
||||
use App\Entity\Season;
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
@@ -21,10 +22,10 @@ final class SeasonVoter extends Voter
|
||||
protected function supports(string $attribute, mixed $subject): bool
|
||||
{
|
||||
return \in_array($attribute, [self::EDIT, self::DELETE, self::ELIMINATION], true)
|
||||
&& $subject instanceof Season;
|
||||
&& ($subject instanceof Season || $subject instanceof Elimination);
|
||||
}
|
||||
|
||||
/** @param Season $subject */
|
||||
/** @param Season|Elimination $subject */
|
||||
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||
{
|
||||
$user = $token->getUser();
|
||||
@@ -36,8 +37,10 @@ final class SeasonVoter extends Voter
|
||||
return true;
|
||||
}
|
||||
|
||||
$season = $subject instanceof Season ? $subject : $subject->getQuiz()->getSeason();
|
||||
|
||||
return match ($attribute) {
|
||||
self::EDIT, self::DELETE, self::ELIMINATION => $subject->isOwner($user),
|
||||
self::EDIT, self::DELETE, self::ELIMINATION => $season->isOwner($user),
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user