diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 296acde19..9ad0c75dd 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -503,7 +503,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface return $collection->count() > 0 ? $collection->first() : NULL; } - public function getOPenParticipations(): Collection + public function getOpenParticipations(): Collection { return $this ->getParticipations() @@ -514,6 +514,11 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface ); } + public function getCurrentParticipations(): Collection + { + return $this->getOpenParticipations(); + } + /** * Return an array with open participations sorted by household * [ diff --git a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php index 5bb5ebe6c..eb8e6de69 100644 --- a/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php +++ b/src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php @@ -6,6 +6,7 @@ use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher; use Chill\MainBundle\Security\Resolver\CenterResolverInterface; use Chill\PersonBundle\Privacy\PrivacyEvent; +use Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -51,9 +52,13 @@ final class SingleTaskController extends AbstractController private LoggerInterface $logger; private CenterResolverDispatcher $centerResolverDispatcher; private TranslatorInterface $translator; + private PaginatorFactory $paginatorFactory; + private SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository; public function __construct( CenterResolverDispatcher $centerResolverDispatcher, + PaginatorFactory $paginatorFactory, + SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, TimelineBuilder $timelineBuilder, @@ -64,6 +69,8 @@ final class SingleTaskController extends AbstractController $this->logger = $logger; $this->translator = $translator; $this->centerResolverDispatcher = $centerResolverDispatcher; + $this->paginatorFactory = $paginatorFactory; + $this->singleTaskAclAwareRepository = $singleTaskAclAwareRepository; } private function getEntityContext(Request $request) @@ -517,10 +524,18 @@ final class SingleTaskController extends AbstractController */ public function myTasksAction() { - return $this->redirectToRoute('chill_task_singletask_list', [ - 'user_id' => $this->getUser()->getId(), - 'hide_form' => true, - 'title' => $this->translator->trans('My tasks') + $this->denyAccessUnlessGranted('ROLE_USER'); + + $nb = $this->singleTaskAclAwareRepository->countByCurrentUsersTasks(); + $paginator = $this->paginatorFactory->create($nb); + $tasks = $this->singleTaskAclAwareRepository->findByCurrentUsersTasks( + null, [], $paginator->getCurrentPageFirstItemNumber(), + $paginator->getItemsPerPage() + ); + + return $this->render('@ChillTask/SingleTask/List/index.html.twig', [ + 'tasks' => $tasks, + 'paginator' => $paginator, ]); } diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php new file mode 100644 index 000000000..e85a6abd7 --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php @@ -0,0 +1,67 @@ +em = $em; + $this->security = $security; + } + + public function findByCurrentUsersTasks( + ?string $pattern = null, + ?array $flags = [], + ?int $start = 0, + ?int $limit = 50, + ?array $orderBy = [] + ): array { + $qb = $this->buildQueryMyTasks($pattern, $flags); + $qb->select('t'); + + $qb + ->setFirstResult($start) + ->setMaxResults($limit) + ; + + foreach ($orderBy as $field => $direction) { + $qb->addOrderBy('t.'.$field, $direction); + } + + return $qb->getQuery()->getResult(); + } + + public function countByCurrentUsersTasks( + ?string $pattern = null, + ?array $flags = [] + ): int { + $qb = $this->buildQueryMyTasks($pattern, $flags); + $qb->select('COUNT(t)'); + + return $qb->getQuery()->getSingleScalarResult(); + } + + public function buildQueryMyTasks( + ?string $pattern = null, + ?array $flags = [] + ): QueryBuilder { + $qb = $this->em->createQueryBuilder(); + $qb + ->from(SingleTask::class, 't') + ->where($qb->expr()->eq('t.assignee', ':user')) + ->setParameter('user', $this->security->getUser()) + ; + + return $qb; + } + +} diff --git a/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php new file mode 100644 index 000000000..b5d83a5f0 --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepositoryInterface.php @@ -0,0 +1,10 @@ + div { margin-bottom: 0.50rem; } - + .chill-task-list__row__title { font-weight: bold; font-size: 1.40rem; } - + .chill-task-list__row__type { font-variant: small-caps; display: inline; @@ -21,31 +29,31 @@ table.chill-task-list { border: 1px solid var(--chill-dark-gray); color: var(--chill-dark-gray); } - + .chill-task-list__row__person-for { display: inline; font-weight: bold; } - + .chill-task-list__row__assignee { display: inline; - + } - + .chill_task-list__row__assignee_by { display: inline; font-weight: bold; } - + .chill-task-list__row__dates { & > ul { display: inline; list-style: none; - + & > li { display: inline; margin-right: 0.25rem; - + } } } diff --git a/src/Bundle/ChillTaskBundle/Resources/public/chill/scss/_task-statuses.scss b/src/Bundle/ChillTaskBundle/Resources/public/chill/scss/_task-statuses.scss index 5e371359e..4f598fc7b 100644 --- a/src/Bundle/ChillTaskBundle/Resources/public/chill/scss/_task-statuses.scss +++ b/src/Bundle/ChillTaskBundle/Resources/public/chill/scss/_task-statuses.scss @@ -1,34 +1,22 @@ +// Access to Bootstrap variables and mixins +@import '~ChillMainAssets/module/bootstrap/shared'; + .task-status { - &.box { - font-variant: small-caps; - display: inline; - padding: .2em .6em .3em; - font-size: 0.88rem; - font-weight: bold; - line-height: 1; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; - color: white; + + // 'new', 'in_progress', 'closed', 'canceled' + &.place-new { + background-color: $chill-yellow; } - - &.type-task_default { - // 'new', 'in_progress', 'closed', 'canceled' - &.place-new { - background-color: var(--chill-yellow); - } - &.place-in_progress { - background-color: var(--chill-green); - } + &.place-in_progress { + background-color: $chill-green; + } - &.place-closed { - background-color: var(--chill-blue); - } + &.place-closed { + background-color: $chill-blue; + } - &.place-canceled { - background-color: var(--chill-beige); - } + &.place-canceled { + background-color: $chill-beige; } } diff --git a/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/index.js b/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/index.js new file mode 100644 index 000000000..a8217c7a7 --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/index.js @@ -0,0 +1 @@ +require("./task_list.scss"); diff --git a/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/task_list.scss b/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/task_list.scss new file mode 100644 index 000000000..4c71462d1 --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Resources/public/page/tile_list/task_list.scss @@ -0,0 +1,24 @@ +.chill-task-list { + .task-type { + font-variant: small-caps; + display: inline; + padding: 0.05rem .15rem; + font-size: 0.88rem; + font-weight: light; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border: 1px solid var(--chill-dark-gray); + color: var(--chill-dark-gray); + } + + .assignee { + text-align: right; + } + + .dates { + text-align: right; + } + +} diff --git a/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig new file mode 100644 index 000000000..87de25ccd --- /dev/null +++ b/src/Bundle/ChillTaskBundle/Resources/views/SingleTask/List/index.html.twig @@ -0,0 +1,153 @@ +{% extends 'ChillMainBundle::layout.html.twig' %} + +{% block title 'My tasks'|trans %} + +{% block content %} +
+ +

{{ block('title') }}

+ + {% if tasks|length == 0 %} +

{{ 'Any tasks'|trans }}

+ {% else %} +
+ {% for task in tasks %} +
+
+
+
+ {{ task.title }} + {% for place in workflow_marked_places(task) %} + + {{ place|trans }} + + {% endfor %} +
+ {% if task.type != 'task_default'%} + + {{ task_workflow_metadata(task, 'definition.name')|trans }} + + {% endif %} +
+ {% if task.person is not null %} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + targetEntity: { name: 'person', id: task.person.id }, + action: 'show', + displayBadge: true, + buttonText: task.person|chill_entity_render_string + } %} + + {% elseif task.course is not null %} + + + + + {% for part in task.course.currentParticipations %} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + targetEntity: { name: 'person', id: part.person.id }, + action: 'show', + displayBadge: true, + buttonText: part.person|chill_entity_render_string + } %} + {% endfor %} + + {% endif %} +
+
+ + +
+
+ {% if task.assignee is not null %} +
+ {{ 'By'|trans }} : + {{ task.assignee.username }} +
+ {% endif %} + + {% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %} +
+
    + {% if task.startDate is not null %} +
  • + + {{ task.startDate|format_date('medium') }} +
  • + {% endif %} + {% if task.warningDate is not null %} +
  • + + {{ task.warningDate|format_date('medium') }} +
  • + {% endif %} + {% if task.endDate is not null %} +
  • + + {{ task.endDate|format_date('medium') }} +
  • + {% endif %} +
+
+ {% endif %} +
+ +
+ +
+
+ + +
+
+ {% endfor %} +
+ {% endif %} + + {{ chill_pagination(paginator) }} + +
+{% endblock %} + +{% block css %} + {{ encore_entry_link_tags('page_task_list') }} +{% endblock %} +{% block js %} + {{ encore_entry_script_tags('page_task_list') }} +{% endblock %} diff --git a/src/Bundle/ChillTaskBundle/chill.webpack.config.js b/src/Bundle/ChillTaskBundle/chill.webpack.config.js index 83c08a6ce..e96855d80 100644 --- a/src/Bundle/ChillTaskBundle/chill.webpack.config.js +++ b/src/Bundle/ChillTaskBundle/chill.webpack.config.js @@ -1,4 +1,6 @@ module.exports = function(encore, entries) { entries.push(__dirname + '/Resources/public/chill/index.js'); + + encore.addEntry('page_task_list', __dirname + '/Resources/public/page/tile_list/index.js'); }; diff --git a/src/Bundle/ChillTaskBundle/config/services/repositories.yaml b/src/Bundle/ChillTaskBundle/config/services/repositories.yaml index 3cc867d96..7bee5abd0 100644 --- a/src/Bundle/ChillTaskBundle/config/services/repositories.yaml +++ b/src/Bundle/ChillTaskBundle/config/services/repositories.yaml @@ -9,3 +9,9 @@ services: arguments: - "@chill.main.security.authorization.helper" Chill\TaskBundle\Repository\SingleTaskRepository: '@chill_task.single_task_repository' + + Chill\TaskBundle\Repository\SingleTaskAclAwareRepository: + autowire: true + autoconfigure: true + + Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface: '@Chill\TaskBundle\Repository\SingleTaskAclAwareRepository' diff --git a/src/Bundle/ChillTaskBundle/translations/messages.fr.yml b/src/Bundle/ChillTaskBundle/translations/messages.fr.yml index fc725195f..76c2c0674 100644 --- a/src/Bundle/ChillTaskBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillTaskBundle/translations/messages.fr.yml @@ -63,6 +63,7 @@ Default task: Tâche par défaut Not assigned: Aucun utilisateur assigné For person: Pour By: Par +Any tasks: Aucune tâche # transitions - default task definition "new": "nouvelle"