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
|
||||
|
||||
<!-- 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
|
||||
* 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
|
||||
@ -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
|
||||
* [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
|
||||
|
||||
* [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\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
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\Routing\Annotation\Route;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class AccompanyingCourseWorkController extends AbstractController
|
||||
{
|
||||
@ -60,7 +61,7 @@ class AccompanyingCourseWorkController extends AbstractController
|
||||
*/
|
||||
public function createWork(AccompanyingPeriod $period): Response
|
||||
{
|
||||
// TODO ACL
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::CREATE, $period);
|
||||
|
||||
if ($period->getSocialIssues()->count() === 0) {
|
||||
$this->addFlash(
|
||||
@ -93,7 +94,8 @@ class AccompanyingCourseWorkController extends AbstractController
|
||||
*/
|
||||
public function deleteWork(AccompanyingPeriodWork $work, Request $request): Response
|
||||
{
|
||||
// TODO ACL
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work);
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$form = $this->createDeleteForm($work->getId());
|
||||
@ -138,7 +140,8 @@ class AccompanyingCourseWorkController extends AbstractController
|
||||
*/
|
||||
public function editWork(AccompanyingPeriodWork $work): Response
|
||||
{
|
||||
// TODO ACL
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::UPDATE, $work);
|
||||
|
||||
$json = $this->serializer->normalize($work, 'json', ['groups' => ['read']]);
|
||||
|
||||
return $this->render('@ChillPerson/AccompanyingCourseWork/edit.html.twig', [
|
||||
@ -157,13 +160,13 @@ class AccompanyingCourseWorkController extends AbstractController
|
||||
*/
|
||||
public function listWorkByAccompanyingPeriod(AccompanyingPeriod $period): Response
|
||||
{
|
||||
// TODO ACL
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodWorkVoter::SEE, $period);
|
||||
|
||||
$totalItems = $this->workRepository->countByAccompanyingPeriod($period);
|
||||
$paginator = $this->paginator->create($totalItems);
|
||||
|
||||
$works = $this->workRepository->findByAccompanyingPeriod(
|
||||
$works = $this->workRepository->findByAccompanyingPeriodOpenFirst(
|
||||
$period,
|
||||
['startDate' => 'DESC', 'endDate' => 'DESC'],
|
||||
$paginator->getItemsPerPage(),
|
||||
$paginator->getCurrentPageFirstItemNumber()
|
||||
);
|
||||
|
@ -13,7 +13,10 @@ namespace Chill\PersonBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@ -24,15 +27,18 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
protected Registry $registry;
|
||||
|
||||
protected Security $security;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator, Registry $registry)
|
||||
public function __construct(TranslatorInterface $translator, Registry $registry, Security $security)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->registry = $registry;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
||||
@ -47,18 +53,21 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
], ])
|
||||
->setExtras(['order' => 10]);
|
||||
|
||||
if ($this->security->isGranted(AccompanyingPeriodVoter::EDIT, $period)) {
|
||||
$menu->addChild($this->translator->trans('Edit Accompanying Course'), [
|
||||
'route' => 'chill_person_accompanying_course_edit',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 20]);
|
||||
}
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT === $period->getStep()) {
|
||||
// no more menu items if the period is draft
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $period)) {
|
||||
$menu->addChild($this->translator->trans('Accompanying Course History'), [
|
||||
'route' => 'chill_person_accompanying_course_history',
|
||||
'routeParameters' => [
|
||||
@ -66,12 +75,6 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
], ])
|
||||
->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'), [
|
||||
'route' => 'chill_person_accompanying_period_comment_list',
|
||||
@ -79,6 +82,17 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
], ])
|
||||
->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');
|
||||
|
||||
|
@ -16,8 +16,10 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
@ -25,8 +27,11 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->em = $entityManager;
|
||||
$this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class);
|
||||
}
|
||||
|
||||
@ -78,6 +83,37 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
|
||||
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
|
||||
{
|
||||
return $this->buildQueryNearEndDateByUser($user, $since, $until)
|
||||
|
@ -23,6 +23,8 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<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;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
@ -20,7 +21,9 @@ use function in_array;
|
||||
|
||||
class AccompanyingPeriodWorkVoter extends Voter
|
||||
{
|
||||
public const CREATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_CREATE';
|
||||
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE';
|
||||
public const UPDATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE';
|
||||
|
||||
private Security $security;
|
||||
|
||||
@ -31,8 +34,14 @@ class AccompanyingPeriodWorkVoter extends Voter
|
||||
|
||||
protected function supports($attribute, $subject): bool
|
||||
{
|
||||
return $subject instanceof AccompanyingPeriodWork
|
||||
&& in_array($attribute, $this->getRoles(), true);
|
||||
return
|
||||
(
|
||||
$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
|
||||
{
|
||||
if ($subject instanceof AccompanyingPeriodWork) {
|
||||
switch ($attribute) {
|
||||
case self::SEE:
|
||||
return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod());
|
||||
return $this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $subject->getAccompanyingPeriod());
|
||||
|
||||
default:
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user