Merge branch '314-improve-admin' into 'master'

Resolve "[admin] Improve admin for document categories"

Closes #314 and #313

See merge request Chill-Projet/chill-bundles!753
This commit is contained in:
LenaertsJ 2024-11-20 13:45:41 +00:00
commit e113e3dce5
12 changed files with 62 additions and 34 deletions

View File

@ -0,0 +1,7 @@
kind: Feature
body: |-
Admin: improve document type admin form with a select field for related class.
Admin: Allow administrator to assign multiple group centers in one go to a user.
time: 2024-11-20T14:05:56.69669451+01:00
custom:
Issue: "314"

View File

@ -17,15 +17,23 @@ use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;
class DocumentCategoryType extends AbstractType class DocumentCategoryType extends AbstractType
{ {
public function __construct(private readonly TranslatorInterface $translator) {}
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$bundles = [ $bundles = [
'chill-doc-store' => 'chill-doc-store', 'chill-doc-store' => 'chill-doc-store',
]; ];
$documentClasses = [
$this->translator->trans('Accompanying period document') => \Chill\DocStoreBundle\Entity\AccompanyingCourseDocument::class,
$this->translator->trans('Person document') => \Chill\DocStoreBundle\Entity\PersonDocument::class,
];
$builder $builder
->add('bundleId', ChoiceType::class, [ ->add('bundleId', ChoiceType::class, [
'choices' => $bundles, 'choices' => $bundles,
@ -34,7 +42,10 @@ class DocumentCategoryType extends AbstractType
->add('idInsideBundle', null, [ ->add('idInsideBundle', null, [
'disabled' => true, 'disabled' => true,
]) ])
->add('documentClass', null, [ ->add('documentClass', ChoiceType::class, [
'choices' => $documentClasses,
'expanded' => false,
'required' => true,
'disabled' => false, 'disabled' => false,
]) ])
->add('name', TranslatableStringFormType::class); ->add('name', TranslatableStringFormType::class);

View File

@ -8,7 +8,7 @@
<table class="table table-bordered border-dark align-middle"> <table class="table table-bordered border-dark align-middle">
<thead> <thead>
<tr> <tr>
<th>{{ 'Creator bundle id' | trans }}</th> {# <th>{{ 'Creator bundle id' | trans }}</th>#}
<th>{{ 'Internal id inside creator bundle' | trans }}</th> <th>{{ 'Internal id inside creator bundle' | trans }}</th>
<th>{{ 'Document class' | trans }}</th> <th>{{ 'Document class' | trans }}</th>
<th>{{ 'Name' | trans }}</th> <th>{{ 'Name' | trans }}</th>
@ -18,7 +18,7 @@
<tbody> <tbody>
{% for document_category in document_categories %} {% for document_category in document_categories %}
<tr> <tr>
<td>{{ document_category.bundleId }}</td> {# <td>{{ document_category.bundleId }}</td>#}
<td>{{ document_category.idInsideBundle }}</td> <td>{{ document_category.idInsideBundle }}</td>
<td>{{ document_category.documentClass }}</td> <td>{{ document_category.documentClass }}</td>
<td>{{ document_category.name | localize_translatable_string}}</td> <td>{{ document_category.name | localize_translatable_string}}</td>

View File

@ -74,6 +74,8 @@ no records found:
Create new category: Créer une nouvelle catégorie Create new category: Créer une nouvelle catégorie
Back to the category list: Retour à la liste Back to the category list: Retour à la liste
Create new DocumentCategory: Créer une nouvelle catégorie de document Create new DocumentCategory: Créer une nouvelle catégorie de document
Accompanying period document: Document de parcours d'accompagnement
Person document: Document de personne
# WOPI EDIT # WOPI EDIT
online_edit_document: Éditer en ligne online_edit_document: Éditer en ligne

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\EventBundle\Entity; namespace Chill\EventBundle\Entity;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/** /**
* Class Status. * Class Status.
@ -36,6 +37,7 @@ class Status
private $name; private $name;
#[ORM\ManyToOne(targetEntity: EventType::class, inversedBy: 'statuses')] #[ORM\ManyToOne(targetEntity: EventType::class, inversedBy: 'statuses')]
#[Assert\NotNull(message: 'An event status must be linked to an event type.')]
private ?EventType $type = null; private ?EventType $type = null;
/** /**

View File

@ -1,10 +1,10 @@
{% extends "@ChillEvent/Admin/index.html.twig" %} {% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
{% block admin_content -%} {% block admin_content -%}
<h1>{{ 'EventType list'|trans }}</h1> <h1>{{ 'EventType list'|trans }}</h1>
<table class="records_list"> <table class="table table-bordered border-dark align-middle">
<thead> <thead>
<tr> <tr>
<th>{{ 'Id'|trans }}</th> <th>{{ 'Id'|trans }}</th>

View File

@ -1,10 +1,10 @@
{% extends "@ChillEvent/Admin/index.html.twig" %} {% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
{% block admin_content -%} {% block admin_content -%}
<h1>{{ 'Role list'|trans }}</h1> <h1>{{ 'Role list'|trans }}</h1>
<table class="records_list"> <table class="table table-bordered border-dark align-middle">
<thead> <thead>
<tr> <tr>
<th>{{ 'Id'|trans }}</th> <th>{{ 'Id'|trans }}</th>

View File

@ -1,10 +1,10 @@
{% extends "@ChillEvent/Admin/index.html.twig" %} {% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
{% block admin_content -%} {% block admin_content -%}
<h1>{{ 'Status list'|trans }}</h1> <h1>{{ 'Status list'|trans }}</h1>
<table class="records_list"> <table class="table table-bordered border-dark align-middle">
<thead> <thead>
<tr> <tr>
<th>{{ 'Id'|trans }}</th> <th>{{ 'Id'|trans }}</th>

View File

@ -12,7 +12,9 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller; namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController; use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\GroupCenter; use Chill\MainBundle\Entity\GroupCenter;
use Chill\MainBundle\Entity\PermissionsGroup;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\ComposedGroupCenterType; use Chill\MainBundle\Form\Type\ComposedGroupCenterType;
use Chill\MainBundle\Form\UserCurrentLocationType; use Chill\MainBundle\Form\UserCurrentLocationType;
@ -64,10 +66,14 @@ class UserController extends CRUDController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isValid()) {
$groupCenter = $this->getPersistedGroupCenter(
$form[self::FORM_GROUP_CENTER_COMPOSED]->getData() $formData = $form[self::FORM_GROUP_CENTER_COMPOSED]->getData();
); $selectedCenters = $formData['center'];
$user->addGroupCenter($groupCenter);
foreach ($selectedCenters as $center) {
$groupCenter = $this->getPersistedGroupCenter($center, $formData['permissionsgroup']);
$user->addGroupCenter($groupCenter);
}
if (0 === $this->validator->validate($user)->count()) { if (0 === $this->validator->validate($user)->count()) {
$em->flush(); $em->flush();
@ -419,17 +425,21 @@ class UserController extends CRUDController
} }
} }
private function getPersistedGroupCenter(GroupCenter $groupCenter) private function getPersistedGroupCenter(Center $center, PermissionsGroup $permissionsGroup)
{ {
$em = $this->managerRegistry->getManager(); $em = $this->managerRegistry->getManager();
$groupCenterManaged = $em->getRepository(GroupCenter::class) $groupCenterManaged = $em->getRepository(GroupCenter::class)
->findOneBy([ ->findOneBy([
'center' => $groupCenter->getCenter(), 'center' => $center,
'permissionsGroup' => $groupCenter->getPermissionsGroup(), 'permissionsGroup' => $permissionsGroup,
]); ]);
if (!$groupCenterManaged) { if (!$groupCenterManaged) {
$groupCenter = new GroupCenter();
$groupCenter->setCenter($center);
$groupCenter->setPermissionsGroup($permissionsGroup);
$em->persist($groupCenter); $em->persist($groupCenter);
return $groupCenter; return $groupCenter;

View File

@ -38,13 +38,13 @@ class GenderType extends AbstractType
'mapped' => true, 'mapped' => true,
'choice_label' => fn (GenderIconEnum $enum) => '<i class="'.strtolower($enum->value).'"></i>', 'choice_label' => fn (GenderIconEnum $enum) => '<i class="'.strtolower($enum->value).'"></i>',
'choice_value' => fn (?GenderIconEnum $enum) => null !== $enum ? $enum->value : null, 'choice_value' => fn (?GenderIconEnum $enum) => null !== $enum ? $enum->value : null,
'label' => 'gender.admin.Select Gender Icon', 'label' => 'gender.admin.Select gender icon',
'label_html' => true, 'label_html' => true,
]) ])
->add('genderTranslation', EnumType::class, [ ->add('genderTranslation', EnumType::class, [
'class' => GenderEnum::class, 'class' => GenderEnum::class,
'choice_label' => fn (GenderEnum $enum) => $enum->value, 'choice_label' => fn (GenderEnum $enum) => $enum->value,
'label' => 'gender.admin.Select Gender Translation', 'label' => 'gender.admin.Select gender translation',
]) ])
->add('active', ChoiceType::class, [ ->add('active', ChoiceType::class, [
'choices' => [ 'choices' => [

View File

@ -13,36 +13,30 @@ namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\PermissionsGroup; use Chill\MainBundle\Entity\PermissionsGroup;
use Doctrine\ORM\EntityRepository; use Chill\MainBundle\Repository\CenterRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ComposedGroupCenterType extends AbstractType class ComposedGroupCenterType extends AbstractType
{ {
public function __construct(private readonly CenterRepository $centerRepository) {}
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$centers = $this->centerRepository->findActive();
$builder->add('permissionsgroup', EntityType::class, [ $builder->add('permissionsgroup', EntityType::class, [
'class' => PermissionsGroup::class, 'class' => PermissionsGroup::class,
'choice_label' => static fn (PermissionsGroup $group) => $group->getName(), 'choice_label' => static fn (PermissionsGroup $group) => $group->getName(),
])->add('center', EntityType::class, [ ])->add('center', ChoiceType::class, [
'class' => Center::class, 'choices' => $centers,
'query_builder' => static function (EntityRepository $er) { 'choice_label' => fn (Center $center) => $center->getName(),
$qb = $er->createQueryBuilder('c'); 'multiple' => true,
$qb->where($qb->expr()->eq('c.isActive', 'TRUE'))
->orderBy('c.name', 'ASC');
return $qb;
},
]); ]);
} }
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('data_class', \Chill\MainBundle\Entity\GroupCenter::class);
}
public function getBlockPrefix() public function getBlockPrefix()
{ {
return 'composed_groupcenter'; return 'composed_groupcenter';

View File

@ -792,5 +792,7 @@ gender:
genderTranslation: traduction grammaticale genderTranslation: traduction grammaticale
not defined: Non défini not defined: Non défini
pick gender: Choisir une genre pick gender: Choisir une genre
Select gender translation: Traduction grammaticale
Select gender icon: Icône à utiliser