mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
change order for accompanying period work list
This commit is contained in:
parent
dc08ced6c9
commit
4314823a70
10
CHANGELOG.md
10
CHANGELOG.md
@ -11,6 +11,13 @@ and this project adheres to
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
<!-- write down unreleased development here -->
|
<!-- write down unreleased development here -->
|
||||||
|
* change order for accompanying course work list
|
||||||
|
|
||||||
|
|
||||||
|
## Test releases
|
||||||
|
|
||||||
|
### test release 2021-02-01
|
||||||
|
|
||||||
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
|
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
|
||||||
* renomme date de début en date d'ouverture dans le formulaire parcours
|
* renomme date de début en date d'ouverture dans le formulaire parcours
|
||||||
* [homepage widget] improve content tables, improve counter pluralization with style on number
|
* [homepage widget] improve content tables, improve counter pluralization with style on number
|
||||||
@ -29,9 +36,6 @@ and this project adheres to
|
|||||||
* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
|
* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
|
||||||
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
|
||||||
|
|
||||||
|
|
||||||
## Test releases
|
|
||||||
|
|
||||||
### test release 2021-01-31
|
### test release 2021-01-31
|
||||||
|
|
||||||
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
|
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
|
||||||
|
@ -15,6 +15,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
|
|||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
@ -23,7 +24,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\Serializer\SerializerInterface;
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
class AccompanyingCourseWorkController extends AbstractController
|
class AccompanyingCourseWorkController extends AbstractController
|
||||||
{
|
{
|
||||||
@ -60,7 +61,7 @@ class AccompanyingCourseWorkController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function createWork(AccompanyingPeriod $period): Response
|
public function createWork(AccompanyingPeriod $period): Response
|
||||||
{
|
{
|
||||||
// TODO ACL
|
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::CREATE, $period);
|
||||||
|
|
||||||
if ($period->getSocialIssues()->count() === 0) {
|
if ($period->getSocialIssues()->count() === 0) {
|
||||||
$this->addFlash(
|
$this->addFlash(
|
||||||
@ -93,7 +94,8 @@ class AccompanyingCourseWorkController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function deleteWork(AccompanyingPeriodWork $work, Request $request): Response
|
public function deleteWork(AccompanyingPeriodWork $work, Request $request): Response
|
||||||
{
|
{
|
||||||
// TODO ACL
|
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work);
|
||||||
|
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
|
||||||
$form = $this->createDeleteForm($work->getId());
|
$form = $this->createDeleteForm($work->getId());
|
||||||
@ -138,7 +140,8 @@ class AccompanyingCourseWorkController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function editWork(AccompanyingPeriodWork $work): Response
|
public function editWork(AccompanyingPeriodWork $work): Response
|
||||||
{
|
{
|
||||||
// TODO ACL
|
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work);
|
||||||
|
|
||||||
$json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]);
|
$json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]);
|
||||||
|
|
||||||
return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [
|
return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [
|
||||||
@ -157,13 +160,13 @@ class AccompanyingCourseWorkController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function listWorkByAccompanyingPeriod(AccompanyingPeriod $period): Response
|
public function listWorkByAccompanyingPeriod(AccompanyingPeriod $period): Response
|
||||||
{
|
{
|
||||||
// TODO ACL
|
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $period);
|
||||||
|
|
||||||
$totalItems = $this->workRepository->countByAccompanyingPeriod($period);
|
$totalItems = $this->workRepository->countByAccompanyingPeriod($period);
|
||||||
$paginator = $this->paginator->create($totalItems);
|
$paginator = $this->paginator->create($totalItems);
|
||||||
|
|
||||||
$works = $this->workRepository->findByAccompanyingPeriod(
|
$works = $this->workRepository->findByAccompanyingPeriodOpenFirst(
|
||||||
$period,
|
$period,
|
||||||
['startDate' => 'DESC', 'endDate' => 'DESC'],
|
|
||||||
$paginator->getItemsPerPage(),
|
$paginator->getItemsPerPage(),
|
||||||
$paginator->getCurrentPageFirstItemNumber()
|
$paginator->getCurrentPageFirstItemNumber()
|
||||||
);
|
);
|
||||||
|
@ -13,7 +13,10 @@ namespace Chill\PersonBundle\Menu;
|
|||||||
|
|
||||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
|
||||||
use Knp\Menu\MenuItem;
|
use Knp\Menu\MenuItem;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Workflow\Registry;
|
use Symfony\Component\Workflow\Registry;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
@ -24,15 +27,18 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
{
|
{
|
||||||
protected Registry $registry;
|
protected Registry $registry;
|
||||||
|
|
||||||
|
protected Security $security;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TranslatorInterface
|
* @var TranslatorInterface
|
||||||
*/
|
*/
|
||||||
protected $translator;
|
protected $translator;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator, Registry $registry)
|
public function __construct(TranslatorInterface $translator, Registry $registry, Security $security)
|
||||||
{
|
{
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->registry = $registry;
|
$this->registry = $registry;
|
||||||
|
$this->security = $security;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
||||||
@ -47,38 +53,46 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
], ])
|
], ])
|
||||||
->setExtras(['order' => 10]);
|
->setExtras(['order' => 10]);
|
||||||
|
|
||||||
$menu->addChild($this->translator->trans('Edit Accompanying Course'), [
|
if ($this->security->isGranted(AccompanyingPeriodVoter::EDIT, $period)) {
|
||||||
'route' => 'chill_person_accompanying_course_edit',
|
$menu->addChild($this->translator->trans('Edit Accompanying Course'), [
|
||||||
'routeParameters' => [
|
'route' => 'chill_person_accompanying_course_edit',
|
||||||
'accompanying_period_id' => $period->getId(),
|
'routeParameters' => [
|
||||||
], ])
|
'accompanying_period_id' => $period->getId(),
|
||||||
->setExtras(['order' => 20]);
|
], ])
|
||||||
|
->setExtras(['order' => 20]);
|
||||||
|
}
|
||||||
|
|
||||||
if (AccompanyingPeriod::STEP_DRAFT === $period->getStep()) {
|
if (AccompanyingPeriod::STEP_DRAFT === $period->getStep()) {
|
||||||
// no more menu items if the period is draft
|
// no more menu items if the period is draft
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$menu->addChild($this->translator->trans('Accompanying Course History'), [
|
if ($this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $period)) {
|
||||||
'route' => 'chill_person_accompanying_course_history',
|
$menu->addChild($this->translator->trans('Accompanying Course History'), [
|
||||||
'routeParameters' => [
|
'route' => 'chill_person_accompanying_course_history',
|
||||||
'accompanying_period_id' => $period->getId(),
|
'routeParameters' => [
|
||||||
], ])
|
'accompanying_period_id' => $period->getId(),
|
||||||
->setExtras(['order' => 30]);
|
], ])
|
||||||
|
->setExtras(['order' => 30]);
|
||||||
|
|
||||||
$menu->addChild($this->translator->trans('Accompanying Course Action'), [
|
|
||||||
'route' => 'chill_person_accompanying_period_work_list',
|
|
||||||
'routeParameters' => [
|
|
||||||
'id' => $period->getId(),
|
|
||||||
], ])
|
|
||||||
->setExtras(['order' => 40]);
|
|
||||||
|
|
||||||
$menu->addChild($this->translator->trans('Accompanying Course Comment'), [
|
$menu->addChild($this->translator->trans('Accompanying Course Comment'), [
|
||||||
'route' => 'chill_person_accompanying_period_comment_list',
|
'route' => 'chill_person_accompanying_period_comment_list',
|
||||||
'routeParameters' => [
|
'routeParameters' => [
|
||||||
'accompanying_period_id' => $period->getId(),
|
'accompanying_period_id' => $period->getId(),
|
||||||
], ])
|
], ])
|
||||||
->setExtras(['order' => 50]);
|
->setExtras(['order' => 50]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->security->isGranted(AccompanyingPeriodWorkVoter::SEE, $period)) {
|
||||||
|
$menu->addChild($this->translator->trans('Accompanying Course Action'), [
|
||||||
|
'route' => 'chill_person_accompanying_period_work_list',
|
||||||
|
'routeParameters' => [
|
||||||
|
'id' => $period->getId(),
|
||||||
|
], ])
|
||||||
|
->setExtras(['order' => 40]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$workflow = $this->registry->get($period, 'accompanying_period_lifecycle');
|
$workflow = $this->registry->get($period, 'accompanying_period_lifecycle');
|
||||||
|
|
||||||
|
@ -16,8 +16,10 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
|||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
@ -25,8 +27,11 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
|
|||||||
{
|
{
|
||||||
private EntityRepository $repository;
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
private EntityManagerInterface $em;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $entityManager)
|
public function __construct(EntityManagerInterface $entityManager)
|
||||||
{
|
{
|
||||||
|
$this->em = $entityManager;
|
||||||
$this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class);
|
$this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +83,37 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
|
|||||||
return $this->repository->findByAccompanyingPeriod($period, $orderBy, $limit, $offset);
|
return $this->repository->findByAccompanyingPeriod($period, $orderBy, $limit, $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of accompanying period with a defined order:
|
||||||
|
*
|
||||||
|
* * first, opened works
|
||||||
|
* * then, closed works
|
||||||
|
*
|
||||||
|
* @return AccompanyingPeriodWork[]
|
||||||
|
*/
|
||||||
|
public function findByAccompanyingPeriodOpenFirst(AccompanyingPeriod $period, int $limit = 10, int $offset = 0): array
|
||||||
|
{
|
||||||
|
$rsm = new ResultSetMappingBuilder($this->em);
|
||||||
|
$rsm->addRootEntityFromClassMetadata(AccompanyingPeriodWork::class, 'w');
|
||||||
|
|
||||||
|
$sql = "SELECT ${rsm} FROM chill_person_accompanying_period_work w
|
||||||
|
WHERE accompanyingPeriod_id = :periodId
|
||||||
|
ORDER BY
|
||||||
|
CASE WHEN enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC,
|
||||||
|
startdate DESC,
|
||||||
|
enddate DESC,
|
||||||
|
id DESC
|
||||||
|
LIMIT :limit OFFSET :offset";
|
||||||
|
|
||||||
|
$nq = $this->em->createNativeQuery($sql, $rsm)
|
||||||
|
->setParameter('periodId', $period->getId(), Types::INTEGER)
|
||||||
|
->setParameter('limit', $limit, Types::INTEGER)
|
||||||
|
->setParameter('offset', $offset, Types::INTEGER)
|
||||||
|
;
|
||||||
|
|
||||||
|
return $nq->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
public function findNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until, int $limit = 20, int $offset = 0): array
|
public function findNearEndDateByUser(User $user, DateTimeImmutable $since, DateTimeImmutable $until, int $limit = 20, int $offset = 0): array
|
||||||
{
|
{
|
||||||
return $this->buildQueryNearEndDateByUser($user, $since, $until)
|
return $this->buildQueryNearEndDateByUser($user, $since, $until)
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_new', { 'id': accompanyingCourse.id }) }}"
|
<a href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_new', { 'id': accompanyingCourse.id }) }}"
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Security\Authorization;
|
namespace Chill\PersonBundle\Security\Authorization;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||||
@ -20,7 +21,9 @@ use function in_array;
|
|||||||
|
|
||||||
class AccompanyingPeriodWorkVoter extends Voter
|
class AccompanyingPeriodWorkVoter extends Voter
|
||||||
{
|
{
|
||||||
|
public const CREATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_CREATE';
|
||||||
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE';
|
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE';
|
||||||
|
public const UPDATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE';
|
||||||
|
|
||||||
private Security $security;
|
private Security $security;
|
||||||
|
|
||||||
@ -31,8 +34,14 @@ class AccompanyingPeriodWorkVoter extends Voter
|
|||||||
|
|
||||||
protected function supports($attribute, $subject): bool
|
protected function supports($attribute, $subject): bool
|
||||||
{
|
{
|
||||||
return $subject instanceof AccompanyingPeriodWork
|
return
|
||||||
&& in_array($attribute, $this->getRoles(), true);
|
(
|
||||||
|
$subject instanceof AccompanyingPeriodWork
|
||||||
|
&& in_array($attribute, $this->getRoles(), true)
|
||||||
|
) || (
|
||||||
|
$subject instanceof AccompanyingPeriod
|
||||||
|
&& in_array($attribute, [self::SEE, self::CREATE])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,13 +50,26 @@ class AccompanyingPeriodWorkVoter extends Voter
|
|||||||
*/
|
*/
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||||
{
|
{
|
||||||
switch ($attribute) {
|
if ($subject instanceof AccompanyingPeriodWork) {
|
||||||
case self::SEE:
|
switch ($attribute) {
|
||||||
return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod());
|
case self::SEE:
|
||||||
|
return $this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $subject->getAccompanyingPeriod());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new UnexpectedValueException("attribute {$attribute} is not supported");
|
throw new UnexpectedValueException("attribute {$attribute} is not supported");
|
||||||
|
}
|
||||||
|
} elseif ($subject instanceof AccompanyingPeriod) {
|
||||||
|
switch ($attribute) {
|
||||||
|
case self::SEE:
|
||||||
|
return $this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $subject);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnexpectedValueException(sprintf("attribute {$attribute} is not supported on instance %s",
|
||||||
|
AccompanyingPeriod::class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new UnexpectedValueException(sprintf("attribute {$attribute} on instance %s is not supported", get_class($subject)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getRoles(): array
|
private function getRoles(): array
|
||||||
|
Loading…
x
Reference in New Issue
Block a user