mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
layout task list
This commit is contained in:
parent
965ea528e3
commit
333a4d94b2
@ -503,7 +503,7 @@ class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
|
|||||||
return $collection->count() > 0 ? $collection->first() : NULL;
|
return $collection->count() > 0 ? $collection->first() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOPenParticipations(): Collection
|
public function getOpenParticipations(): Collection
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
->getParticipations()
|
->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
|
* Return an array with open participations sorted by household
|
||||||
* [
|
* [
|
||||||
|
@ -6,6 +6,7 @@ use Chill\MainBundle\Entity\Scope;
|
|||||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||||
use Chill\MainBundle\Security\Resolver\CenterResolverInterface;
|
use Chill\MainBundle\Security\Resolver\CenterResolverInterface;
|
||||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||||
|
use Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
@ -51,9 +52,13 @@ final class SingleTaskController extends AbstractController
|
|||||||
private LoggerInterface $logger;
|
private LoggerInterface $logger;
|
||||||
private CenterResolverDispatcher $centerResolverDispatcher;
|
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||||
private TranslatorInterface $translator;
|
private TranslatorInterface $translator;
|
||||||
|
private PaginatorFactory $paginatorFactory;
|
||||||
|
private SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CenterResolverDispatcher $centerResolverDispatcher,
|
CenterResolverDispatcher $centerResolverDispatcher,
|
||||||
|
PaginatorFactory $paginatorFactory,
|
||||||
|
SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository,
|
||||||
TranslatorInterface $translator,
|
TranslatorInterface $translator,
|
||||||
EventDispatcherInterface $eventDispatcher,
|
EventDispatcherInterface $eventDispatcher,
|
||||||
TimelineBuilder $timelineBuilder,
|
TimelineBuilder $timelineBuilder,
|
||||||
@ -64,6 +69,8 @@ final class SingleTaskController extends AbstractController
|
|||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
|
$this->paginatorFactory = $paginatorFactory;
|
||||||
|
$this->singleTaskAclAwareRepository = $singleTaskAclAwareRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getEntityContext(Request $request)
|
private function getEntityContext(Request $request)
|
||||||
@ -517,10 +524,18 @@ final class SingleTaskController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function myTasksAction()
|
public function myTasksAction()
|
||||||
{
|
{
|
||||||
return $this->redirectToRoute('chill_task_singletask_list', [
|
$this->denyAccessUnlessGranted('ROLE_USER');
|
||||||
'user_id' => $this->getUser()->getId(),
|
|
||||||
'hide_form' => true,
|
$nb = $this->singleTaskAclAwareRepository->countByCurrentUsersTasks();
|
||||||
'title' => $this->translator->trans('My tasks')
|
$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,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\TaskBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\TaskBundle\Entity\SingleTask;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepositoryInterface
|
||||||
|
{
|
||||||
|
private EntityManagerInterface $em;
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em, Security $security)
|
||||||
|
{
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\TaskBundle\Repository;
|
||||||
|
|
||||||
|
interface SingleTaskAclAwareRepositoryInterface
|
||||||
|
{
|
||||||
|
public function findByCurrentUsersTasks(?string $pattern = null, ?array $flags = [], ?int $start = 0, ?int $limit = 50, ?array $orderBy = []): array;
|
||||||
|
|
||||||
|
public function countByCurrentUsersTasks(?string $pattern = null, ?array $flags = []): int;
|
||||||
|
}
|
@ -1,13 +1,21 @@
|
|||||||
|
/*
|
||||||
|
!!!!!!!
|
||||||
|
This is a legacy version for task list. The new task are now
|
||||||
|
layed out in page/tile_list/index.js
|
||||||
|
!!!!!!
|
||||||
|
*/
|
||||||
|
|
||||||
table.chill-task-list {
|
table.chill-task-list {
|
||||||
|
|
||||||
.chill-task-list__row > div {
|
.chill-task-list__row > div {
|
||||||
margin-bottom: 0.50rem;
|
margin-bottom: 0.50rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill-task-list__row__title {
|
.chill-task-list__row__title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.40rem;
|
font-size: 1.40rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill-task-list__row__type {
|
.chill-task-list__row__type {
|
||||||
font-variant: small-caps;
|
font-variant: small-caps;
|
||||||
display: inline;
|
display: inline;
|
||||||
@ -21,31 +29,31 @@ table.chill-task-list {
|
|||||||
border: 1px solid var(--chill-dark-gray);
|
border: 1px solid var(--chill-dark-gray);
|
||||||
color: var(--chill-dark-gray);
|
color: var(--chill-dark-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill-task-list__row__person-for {
|
.chill-task-list__row__person-for {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill-task-list__row__assignee {
|
.chill-task-list__row__assignee {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill_task-list__row__assignee_by {
|
.chill_task-list__row__assignee_by {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chill-task-list__row__dates {
|
.chill-task-list__row__dates {
|
||||||
& > ul {
|
& > ul {
|
||||||
display: inline;
|
display: inline;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
||||||
& > li {
|
& > li {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,22 @@
|
|||||||
|
// Access to Bootstrap variables and mixins
|
||||||
|
@import '~ChillMainAssets/module/bootstrap/shared';
|
||||||
|
|
||||||
.task-status {
|
.task-status {
|
||||||
&.box {
|
|
||||||
font-variant: small-caps;
|
// 'new', 'in_progress', 'closed', 'canceled'
|
||||||
display: inline;
|
&.place-new {
|
||||||
padding: .2em .6em .3em;
|
background-color: $chill-yellow;
|
||||||
font-size: 0.88rem;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 1;
|
|
||||||
text-align: center;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: baseline;
|
|
||||||
border-radius: .25em;
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.type-task_default {
|
|
||||||
// 'new', 'in_progress', 'closed', 'canceled'
|
|
||||||
&.place-new {
|
|
||||||
background-color: var(--chill-yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.place-in_progress {
|
&.place-in_progress {
|
||||||
background-color: var(--chill-green);
|
background-color: $chill-green;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.place-closed {
|
&.place-closed {
|
||||||
background-color: var(--chill-blue);
|
background-color: $chill-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.place-canceled {
|
&.place-canceled {
|
||||||
background-color: var(--chill-beige);
|
background-color: $chill-beige;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
require("./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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
{% extends 'ChillMainBundle::layout.html.twig' %}
|
||||||
|
|
||||||
|
{% block title 'My tasks'|trans %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-md-10 col-xxl">
|
||||||
|
|
||||||
|
<h1>{{ block('title') }}</h1>
|
||||||
|
|
||||||
|
{% if tasks|length == 0 %}
|
||||||
|
<p class="chill-no-data-statement">{{ 'Any tasks'|trans }}</p>
|
||||||
|
{% else %}
|
||||||
|
<div class="flex-table chill-task-list">
|
||||||
|
{% for task in tasks %}
|
||||||
|
<div class="item-bloc">
|
||||||
|
<div class="item-row">
|
||||||
|
<div class="item-col">
|
||||||
|
<div class="denomination h2">
|
||||||
|
{{ task.title }}
|
||||||
|
{% for place in workflow_marked_places(task) %}
|
||||||
|
<span class="task-status badge type-{{ task.type }} place-{{ place }}">
|
||||||
|
{{ place|trans }}
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% if task.type != 'task_default'%}
|
||||||
|
<span class="task-type">
|
||||||
|
{{ task_workflow_metadata(task, 'definition.name')|trans }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
{% if task.person is not null %}
|
||||||
|
<span class="chill-task-list__row__person">
|
||||||
|
{% 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
|
||||||
|
} %}
|
||||||
|
</span>
|
||||||
|
{% elseif task.course is not null %}
|
||||||
|
<a href="{{ path('chill_person_accompanying_course_index', { 'accompanying_period_id': task.course.id }) }}"
|
||||||
|
class="btn btn-sm btn-outline-primary" title="{{ 'See accompanying period'|trans }}">
|
||||||
|
<i class="fa fa-random fa-fw"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{% 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 %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="item-col">
|
||||||
|
<div class="container">
|
||||||
|
{% if task.assignee is not null %}
|
||||||
|
<div class="assignee row">
|
||||||
|
<span class="chill_task-list__row__assignee_by">{{ 'By'|trans }} :</span>
|
||||||
|
<span>{{ task.assignee.username }}</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %}
|
||||||
|
<div class="dates row">
|
||||||
|
<ul class="column">
|
||||||
|
{% if task.startDate is not null %}
|
||||||
|
<li title="{{ 'Start'|trans|escape('html_attr') }}">
|
||||||
|
<i class="fa fa-play"></i>
|
||||||
|
{{ task.startDate|format_date('medium') }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if task.warningDate is not null %}
|
||||||
|
<li title="{{ 'Warning'|trans|escape('html_attr') }}">
|
||||||
|
<i class="fa fa-exclamation-triangle"></i>
|
||||||
|
{{ task.warningDate|format_date('medium') }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if task.endDate is not null %}
|
||||||
|
<li title="{{ 'End'|trans|escape('html_attr') }}">
|
||||||
|
<i class="fa fa-hourglass-end"></i>
|
||||||
|
{{ task.endDate|format_date('medium') }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="item-row separator">
|
||||||
|
<ul class="record_actions">
|
||||||
|
{% if workflow_transitions(task)|length > 0 %}
|
||||||
|
<li>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-task-exchange dropdown-toggle" href="#" role="button" id="taskExchange" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
{{'Change task status'|trans}}
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="taskExchange">
|
||||||
|
{% for transition in workflow_transitions(task) %}
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{{ path('chill_task_task_transition', { 'taskId': task.id, 'transition': transition.name, 'kind': 'single-task', 'list_params': app.request.query.all }) }}" class="{{ task_workflow_metadata(task, 'transition.class', transition)|e('html_attr') }}">
|
||||||
|
{{ task_workflow_metadata(task, 'transition.verb', transition)|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('chill_task_single_task_show', { 'id': task.id, 'list_params': app.request.query.all }) }}" class="btn btn-show "></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{# {% if is_granted('CHILL_TASK_TASK_UPDATE', task) %} #}
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('chill_task_single_task_edit', { 'id': task.id, 'list_params': app.request.query.all }) }}" class="btn btn-update "></a>
|
||||||
|
</li>
|
||||||
|
{# {% endif %} #}
|
||||||
|
|
||||||
|
{# {% if is_granted('CHILL_TASK_TASK_DELETE', task) %} #}
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('chill_task_single_task_delete', { 'id': task.id, 'list_params': app.request.query.all } ) }}" class="btn btn-delete "></a>
|
||||||
|
</li>
|
||||||
|
{# {% endif %} #}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{{ encore_entry_link_tags('page_task_list') }}
|
||||||
|
{% endblock %}
|
||||||
|
{% block js %}
|
||||||
|
{{ encore_entry_script_tags('page_task_list') }}
|
||||||
|
{% endblock %}
|
@ -1,4 +1,6 @@
|
|||||||
module.exports = function(encore, entries)
|
module.exports = function(encore, entries)
|
||||||
{
|
{
|
||||||
entries.push(__dirname + '/Resources/public/chill/index.js');
|
entries.push(__dirname + '/Resources/public/chill/index.js');
|
||||||
|
|
||||||
|
encore.addEntry('page_task_list', __dirname + '/Resources/public/page/tile_list/index.js');
|
||||||
};
|
};
|
||||||
|
@ -9,3 +9,9 @@ services:
|
|||||||
arguments:
|
arguments:
|
||||||
- "@chill.main.security.authorization.helper"
|
- "@chill.main.security.authorization.helper"
|
||||||
Chill\TaskBundle\Repository\SingleTaskRepository: '@chill_task.single_task_repository'
|
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'
|
||||||
|
@ -63,6 +63,7 @@ Default task: Tâche par défaut
|
|||||||
Not assigned: Aucun utilisateur assigné
|
Not assigned: Aucun utilisateur assigné
|
||||||
For person: Pour
|
For person: Pour
|
||||||
By: Par
|
By: Par
|
||||||
|
Any tasks: Aucune tâche
|
||||||
|
|
||||||
# transitions - default task definition
|
# transitions - default task definition
|
||||||
"new": "nouvelle"
|
"new": "nouvelle"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user