Compare commits

..

2 Commits

Author SHA1 Message Date
714d0ed991 DX [changie] 2023-06-07 19:40:56 +02:00
ed96017c49 FEATURE [task filter][person] filter tasks on the basis of a person 2023-06-07 19:38:24 +02:00
52 changed files with 331 additions and 1104 deletions

View File

@@ -0,0 +1,6 @@
kind: DX
body: Add methods to RegroupmentRepository and fullfill Center / Regroupment Doctrine
mapping
time: 2023-06-07T13:03:44.177864269+02:00
custom:
Issue: ""

View File

@@ -0,0 +1,6 @@
kind: Feature
body: Add the possibility to filter tasks on the basis of the person involved. Expansion
of FilterOrderHelper.
time: 2023-06-07T19:40:40.506964817+02:00
custom:
Issue: ""

View File

@@ -0,0 +1,7 @@
kind: Security
body: Rights are checked for display of 'accompanying period' tab in household menu.
Rights are also checked for creation of 'accompanying period' from within household
context
time: 2023-06-07T17:47:02.488819553+02:00
custom:
Issue: "105"

View File

@@ -1,17 +0,0 @@
## v2.1.0 - 2023-06-12
### Feature
* [docgen] allow to pick a third party when generating a document in context Activity, AccompanyingPeriod
### Fixed
* ([#111](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/111)) List of "my accompanying periods": separate the active and closed periods in two different lists, and show the inactive_long and inactive_short periods
### Security
* ([#105](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/105)) Rights are checked for display of 'accompanying period' tab in household menu. Rights are also checked for creation of 'accompanying period' from within household context
### DX
* Add methods to RegroupmentRepository and fullfill Center / Regroupment Doctrine mapping

View File

@@ -1,12 +0,0 @@
## v2.2.0 - 2023-06-18
### Feature
* When navigating from a workflow regarding to an evaluation's document to an accompanying course, scroll directly to the document, and blink to highlight this document
* Add notification to accompanying period work and work's evaluation's documents
* ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[Export] Filter accompanying period by step at date: allow to pick multiple steps
* ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[export] add a filter on accompanying period: filter by step between two dates
### Fixed
* use the correct annotation for the association between PersonCurrentCenter and Person
* ([#58](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/58))Fix birthdate timezone in PersonRenderBox
* ([#55](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/55))Fix the notification counter
### DX
* DQL function OVERLAPSI: simplify expression in postgresql

View File

@@ -6,37 +6,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
## v2.2.0 - 2023-06-18
### Feature
* When navigating from a workflow regarding to an evaluation's document to an accompanying course, scroll directly to the document, and blink to highlight this document
* Add notification to accompanying period work and work's evaluation's documents
* ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[Export] Filter accompanying period by step at date: allow to pick multiple steps
* ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[export] add a filter on accompanying period: filter by step between two dates
### Fixed
* use the correct annotation for the association between PersonCurrentCenter and Person
* ([#58](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/58))Fix birthdate timezone in PersonRenderBox
* ([#55](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/55))Fix the notification counter
### DX
* DQL function OVERLAPSI: simplify expression in postgresql
## v2.1.0 - 2023-06-12
### Feature
* [docgen] allow to pick a third party when generating a document in context Activity, AccompanyingPeriod
### Fixed
* ([#111](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/111)) List of "my accompanying periods": separate the active and closed periods in two different lists, and show the inactive_long and inactive_short periods
### Security
* ([#105](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/105)) Rights are checked for display of 'accompanying period' tab in household menu. Rights are also checked for creation of 'accompanying period' from within household context
### DX
* Add methods to RegroupmentRepository and fullfill Center / Regroupment Doctrine mapping
## 2.0.0
* this is a release to relaunch our proceess of release with semantic versioning

View File

@@ -44,9 +44,3 @@ async function download_and_open(event: Event): Promise<void> {
}
</script>
<style scoped lang="sass">
i.fa::before {
color: var(--bs-dropdown-link-hover-color);
}
</style>

View File

@@ -88,9 +88,3 @@ async function download_and_open(event: Event): Promise<void> {
console.log('open button should have been clicked');
}
</script>
<style scoped lang="sass">
i.fa::before {
color: var(--bs-dropdown-link-hover-color);
}
</style>

View File

@@ -40,8 +40,5 @@ async function beforeLeave(event: Event): Promise<true> {
</script>
<style scoped lang="sass">
i.fa::before {
color: var(--bs-dropdown-link-hover-color);
}
</style>

View File

@@ -1,5 +1,5 @@
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
<div class="d-inline-flex"
<div
data-download-buttons
data-stored-object="{{ document_json|json_encode|escape('html_attr') }}"
data-can-edit="{{ can_edit ? '1' : '0' }}"

View File

@@ -18,7 +18,6 @@ No document found: Aucun document trouvé
The document is successfully registered: Le document est enregistré
The document is successfully updated: Le document est mis à jour
Any description: Aucune description
See the document: Voir le document
document:
Any title: Aucun titre

View File

@@ -90,14 +90,16 @@ class OverlapsI extends FunctionNode
if ($part instanceof PathExpression) {
return sprintf(
"COALESCE(%s, '%s'::date)",
"CASE WHEN %s IS NOT NULL THEN %s ELSE '%s'::date END",
$part->dispatch($sqlWalker),
$part->dispatch($sqlWalker),
$p
);
}
return sprintf(
"COALESCE(%s::date, '%s'::date)",
"CASE WHEN %s::date IS NOT NULL THEN %s::date ELSE '%s'::date END",
$part->dispatch($sqlWalker),
$part->dispatch($sqlWalker),
$p
);

View File

@@ -13,6 +13,8 @@ namespace Chill\MainBundle\Form\Type\Listing;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Chill\PersonBundle\Form\Type\PickPersonType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SearchType;
@@ -97,6 +99,30 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
$builder->add($dateRangesBuilder);
}
if (0 < count($helper->getPersonPickers())) {
$personPickersBuilder = $builder->create('personPicker', null, ['compound' => true]);
foreach ($helper->getPersonPickers() as $name => $opts) {
$personPicker = $personPickersBuilder->create($name, null, [
'compound' => true,
'label' => null === $opts['label'] ? false : $opts['label'] ?? $name,
]);
$personPicker->add(
'person',
PickPersonDynamicType::class,
[
'multiple' => false,
]
);
$personPickersBuilder->add($personPicker);
}
$builder->add($personPickersBuilder);
}
foreach ($this->requestStack->getCurrentRequest()->query->getIterator() as $key => $value) {
switch ($key) {
case 'q':

View File

@@ -34,13 +34,9 @@ class NotificationPresence
$this->notificationRepository = $notificationRepository;
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
* @return array{unread: int, sent: int, total: int}
*/
public function countNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): array
public function countNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
{
if ([] === $more && array_key_exists($relatedEntityClass, $this->cache) && array_key_exists($relatedEntityId, $this->cache[$relatedEntityClass])) {
if (array_key_exists($relatedEntityClass, $this->cache) && array_key_exists($relatedEntityId, $this->cache[$relatedEntityClass])) {
return $this->cache[$relatedEntityClass][$relatedEntityId];
}
@@ -50,25 +46,21 @@ class NotificationPresence
$counter = $this->notificationRepository->countNotificationByRelatedEntityAndUserAssociated(
$relatedEntityClass,
$relatedEntityId,
$user,
$more
$user
);
if ([] === $more) {
$this->cache[$relatedEntityClass][$relatedEntityId] = $counter;
}
$this->cache[$relatedEntityClass][$relatedEntityId] = $counter;
return $counter;
}
return ['unread' => 0, 'sent' => 0, 'total' => 0];
return ['unread' => 0, 'read' => 0];
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
* @return array|Notification[]
*/
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId, array $more = []): array
public function getNotificationsForClassAndEntity(string $relatedEntityClass, int $relatedEntityId): array
{
$user = $this->security->getUser();
@@ -76,8 +68,7 @@ class NotificationPresence
return $this->notificationRepository->findNotificationByRelatedEntityAndUserAssociated(
$relatedEntityClass,
$relatedEntityId,
$user,
$more
$user
);
}

View File

@@ -34,30 +34,24 @@ class NotificationTwigExtensionRuntime implements RuntimeExtensionInterface
$this->urlGenerator = $urlGenerator;
}
public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): string
public function counterNotificationFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
{
return $environment->render(
'@ChillMain/Notification/extension_counter_notifications_for.html.twig',
[
'counter' => $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more),
'counter' => $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId),
]
);
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
*/
public function countNotificationsFor(string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): array
public function countNotificationsFor(string $relatedEntityClass, int $relatedEntityId, array $options = []): array
{
return $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more);
return $this->notificationPresence->countNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
*/
public function listNotificationsFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $more = [], array $options = []): string
public function listNotificationsFor(Environment $environment, string $relatedEntityClass, int $relatedEntityId, array $options = []): string
{
$notifications = $this->notificationPresence->getNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId, $more);
$notifications = $this->notificationPresence->getNotificationsForClassAndEntity($relatedEntityClass, $relatedEntityId);
if ([] === $notifications) {
return '';

View File

@@ -29,15 +29,6 @@ final class NotificationRepository implements ObjectRepository
private EntityRepository $repository;
private const BASE_COUNTER_SQL = <<<'SQL'
SELECT
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_unread cmnau WHERE user_id = :userid and cmnau.notification_id = cmn.id))::int) AS unread,
SUM((cmn.sender_id = :userid)::int) AS sent,
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_user cmnau_all WHERE user_id = :userid and cmnau_all.notification_id = cmn.id))::int) + SUM((cmn.sender_id = :userid)::int) AS total
FROM chill_main_notification cmn
SQL;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
@@ -60,45 +51,29 @@ final class NotificationRepository implements ObjectRepository
->getSingleScalarResult();
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
* @return array{unread: int, sent: int, total: int}
*/
public function countNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more = []): array
public function countNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
{
$sqlParams = ['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId, 'userid' => $user->getId()];
if (null === $this->notificationByRelatedEntityAndUserAssociatedStatement) {
$sql =
'SELECT
SUM((EXISTS (SELECT 1 AS c FROM chill_main_notification_addresses_unread cmnau WHERE user_id = :userid and cmnau.notification_id = cmn.id))::int) AS unread,
SUM((cmn.sender_id = :userid)::int) AS sent,
COUNT(cmn.*) AS total
FROM chill_main_notification cmn
WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
if ([] === $more) {
if (null === $this->notificationByRelatedEntityAndUserAssociatedStatement) {
$sql = self::BASE_COUNTER_SQL . ' WHERE relatedentityclass = :relatedEntityClass AND relatedentityid = :relatedEntityId AND sender_id IS NOT NULL';
$this->notificationByRelatedEntityAndUserAssociatedStatement =
$this->em->getConnection()->prepare($sql);
}
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
->executeQuery($sqlParams);
$result = $results->fetchAssociative();
$results->free();
} else {
$wheres = [];
foreach ([
['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId],
...$more
] as $k => ['relatedEntityClass' => $relClass, 'relatedEntityId' => $relId]) {
$wheres[] = "(relatedEntityClass = :relatedEntityClass_{$k} AND relatedEntityId = :relatedEntityId_{$k})";
$sqlParams["relatedEntityClass_{$k}"] = $relClass;
$sqlParams["relatedEntityId_{$k}"] = $relId;
}
$sql = self::BASE_COUNTER_SQL . ' WHERE sender_id IS NOT NULL AND (' . implode(' OR ', $wheres) . ')';
$result = $this->em->getConnection()->fetchAssociative($sql, $sqlParams);
$this->notificationByRelatedEntityAndUserAssociatedStatement =
$this->em->getConnection()->prepare($sql);
}
return array_map(fn (?int $number) => $number ?? 0, $result);
$results = $this->notificationByRelatedEntityAndUserAssociatedStatement
->executeQuery(['relatedEntityClass' => $relatedEntityClass, 'relatedEntityId' => $relatedEntityId, 'userid' => $user->getId()]);
$result = $results->fetchAssociative();
$results->free();
return $result;
}
public function countUnreadByUser(User $user): int
@@ -192,8 +167,8 @@ final class NotificationRepository implements ObjectRepository
}
/**
* @param int|null $limit
* @param int|null $offset
* @param mixed|null $limit
* @param mixed|null $offset
*
* @return Notification[]
*/
@@ -203,15 +178,13 @@ final class NotificationRepository implements ObjectRepository
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
* @return array|Notification[]
*/
public function findNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more): array
public function findNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): array
{
return
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user, $more)
$this->buildQueryNotificationByRelatedEntityAndUserAssociated($relatedEntityClass, $relatedEntityId, $user)
->select('n')
->addOrderBy('n.date', 'DESC')
->getQuery()
->getResult();
}
@@ -249,36 +222,13 @@ final class NotificationRepository implements ObjectRepository
return Notification::class;
}
/**
* @param list<array{relatedEntityClass: class-string, relatedEntityId: int}> $more
*/
private function buildQueryNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user, array $more = []): QueryBuilder
private function buildQueryNotificationByRelatedEntityAndUserAssociated(string $relatedEntityClass, int $relatedEntityId, User $user): QueryBuilder
{
$qb = $this->repository->createQueryBuilder('n');
// add condition for related entity (in main arguments, and in more)
$or = $qb->expr()->orX($qb->expr()->andX(
$qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'),
$qb->expr()->eq('n.relatedEntityId', ':relatedEntityId')
));
$qb
->setParameter('relatedEntityClass', $relatedEntityClass)
->setParameter('relatedEntityId', $relatedEntityId);
foreach ($more as $k => ['relatedEntityClass' => $relatedClass, 'relatedEntityId' => $relatedId]) {
$or->add(
$qb->expr()->andX(
$qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass_'.$k),
$qb->expr()->eq('n.relatedEntityId', ':relatedEntityId_'.$k)
)
);
$qb
->setParameter('relatedEntityClass_'.$k, $relatedClass)
->setParameter('relatedEntityId_'.$k, $relatedId);
}
$qb
->andWhere($or)
->where($qb->expr()->eq('n.relatedEntityClass', ':relatedEntityClass'))
->andWhere($qb->expr()->eq('n.relatedEntityId', ':relatedEntityId'))
->andWhere($qb->expr()->isNotNull('n.sender'))
->andWhere(
$qb->expr()->orX(
@@ -286,6 +236,8 @@ final class NotificationRepository implements ObjectRepository
$qb->expr()->eq('n.sender', ':user')
)
)
->setParameter('relatedEntityClass', $relatedEntityClass)
->setParameter('relatedEntityId', $relatedEntityId)
->setParameter('user', $user);
return $qb;

View File

@@ -34,6 +34,35 @@
{% endfor %}
{% endif %}
{% endif %}
{% if form.personPicker is defined %}
{% if form.personPicker|length > 0 %}
{% for personPickerName, options in form.personPicker %}
<div class="row gx-0">
{% if form.personPicker[personPickerName].vars.label is not same as(false) %}
<div class="col-md-2">
{{ form_label(form.personPicker[personPickerName])}}
</div>
{% endif %}
<div class="col-md-9">
{{ form_widget(form.personPicker[personPickerName]) }}
</div>
</div>
{% if form.checkboxes is not defined %}
<div class="row gx-0">
<div class="col-md-12">
<ul class="record_actions">
<li>
<button type="submit" class="btn btn-misc"><i class="fa fa-filter"></i></button>
</li>
</ul>
</div>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% if form.checkboxes is defined %}
{% if form.checkboxes|length > 0 %}
{% for checkbox_name, options in form.checkboxes %}
@@ -61,5 +90,6 @@
{% endfor %}
{% endif %}
{% endif %}
</div>
{{ form_end(form) }}

View File

@@ -9,4 +9,4 @@
{{ 'notification.counter unread notifications'|trans({'unread': counter.unread }) }}
</span>
{% endif %}
</div>
</div>

View File

@@ -26,6 +26,8 @@ class FilterOrderHelper
private array $dateRanges = [];
private array $personPickers = [];
private FormFactoryInterface $formFactory;
private ?string $formName = 'f';
@@ -70,6 +72,13 @@ class FilterOrderHelper
return $this;
}
public function addPersonPickers(string $name, ?string $label = null): self
{
$this->personPickers[$name] = ['label' => $label];
return $this;
}
public function buildForm(): FormInterface
{
return $this->formFactory
@@ -91,6 +100,16 @@ class FilterOrderHelper
return $this->checkboxes;
}
public function getPersonPickers(): array
{
return $this->personPickers;
}
public function getPersonPickerData(string $name): array
{
return $this->getFormData()['personPickers'][$name];
}
/**
* @return array<'to': DateTimeImmutable, 'from': DateTimeImmutable>
*/
@@ -133,6 +152,10 @@ class FilterOrderHelper
$r['checkboxes'][$name] = $c['default'];
}
foreach ($this->personPickers as $name => $defaults) {
$r['personPickers'][$name]['label'] = $defaults['label'];
}
foreach ($this->dateRanges as $name => $defaults) {
$r['dateRanges'][$name]['from'] = $defaults['from'];
$r['dateRanges'][$name]['to'] = $defaults['to'];

View File

@@ -21,6 +21,8 @@ class FilterOrderHelperBuilder
private array $dateRanges = [];
private array $personPickers = [];
private FormFactoryInterface $formFactory;
private RequestStack $requestStack;
@@ -56,6 +58,13 @@ class FilterOrderHelperBuilder
return $this;
}
public function addPersonPicker(string $name, ?string $label = null): self
{
$this->personPickers[$name] = ['label' => $label];
return $this;
}
public function build(): FilterOrderHelper
{
$helper = new FilterOrderHelper(
@@ -85,6 +94,14 @@ class FilterOrderHelperBuilder
$helper->addDateRange($name, $label, $from, $to);
}
foreach (
$this->personPickers as $name => [
'label' => $label,
]
) {
$helper->addPersonPickers($name, $label);
}
return $helper;
}
}

View File

@@ -12,11 +12,9 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class UserAccompanyingPeriodController extends AbstractController
@@ -34,24 +32,12 @@ class UserAccompanyingPeriodController extends AbstractController
/**
* @Route("/{_locale}/person/accompanying-periods/my", name="chill_person_accompanying_period_user")
*/
public function listAction(Request $request): Response
public function listAction(Request $request)
{
$active = $request->query->getBoolean('active', true);
$steps = match ($active) {
true => [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
],
false => [
AccompanyingPeriod::STEP_CLOSED,
]
};
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => $steps]);
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']]);
$pagination = $this->paginatorFactory->create($total);
$accompanyingPeriods = $this->accompanyingPeriodRepository->findBy(
['user' => $this->getUser(), 'step' => $steps],
['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']],
['openingDate' => 'DESC'],
$pagination->getItemsPerPage(),
$pagination->getCurrentPageFirstItemNumber()
@@ -60,14 +46,13 @@ class UserAccompanyingPeriodController extends AbstractController
return $this->render('@ChillPerson/AccompanyingPeriod/user_periods_list.html.twig', [
'accompanyingPeriods' => $accompanyingPeriods,
'pagination' => $pagination,
'active' => $active,
]);
}
/**
* @Route("/{_locale}/person/accompanying-periods/my/drafts", name="chill_person_accompanying_period_draft_user")
*/
public function listDraftsAction(): Response
public function listDraftsAction(Request $request)
{
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => 'DRAFT']);
$pagination = $this->paginatorFactory->create($total);

View File

@@ -59,7 +59,6 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
* )
* @Serializer\Groups({"read", "docgen:read"})
* @ORM\OrderBy({"startDate": "DESC", "id": "DESC"})
* @var Collection<AccompanyingPeriodWorkEvaluation>
*
* @internal /!\ the serialization for write evaluations is handled in `AccompanyingPeriodWorkDenormalizer`
*/
@@ -279,9 +278,6 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
return $this->accompanyingPeriod;
}
/**
* @return Collection<AccompanyingPeriodWorkEvaluation>
*/
public function getAccompanyingPeriodWorkEvaluations(): Collection
{
return $this->accompanyingPeriodWorkEvaluations;

View File

@@ -79,7 +79,6 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
* )
* @ORM\OrderBy({"createdAt": "DESC", "id": "DESC"})
* @Serializer\Groups({"read"})
* @var Collection<AccompanyingPeriodWorkEvaluationDocument>
*/
private Collection $documents;
@@ -205,7 +204,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
}
/**
* @return Collection<AccompanyingPeriodWorkEvaluationDocument>
* @return Collection
*/
public function getDocuments()
{

View File

@@ -45,7 +45,7 @@ class PersonCenterCurrent
private ?int $id = null;
/**
* @ORM\OneToOne(targetEntity=Person::class, inversedBy="centerCurrent")
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerCurrent")
*/
private Person $person;

View File

@@ -23,15 +23,11 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function in_array;
class StepFilterOnDate implements FilterInterface
class StepFilter implements FilterInterface
{
private const A = 'acp_filter_bystep_stephistories';
private const DEFAULT_CHOICE = [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private const DEFAULT_CHOICE = AccompanyingPeriod::STEP_CONFIRMED;
private const P = 'acp_step_filter_date';
@@ -83,7 +79,7 @@ class StepFilterOnDate implements FilterInterface
$qb->expr()->in(self::A . '.step', ':acp_filter_by_step_steps')
)
->setParameter(self::P, $this->rollingDateConverter->convert($data['calc_date']))
->setParameter('acp_filter_by_step_steps', $data['accepted_steps_multi']);
->setParameter('acp_filter_by_step_steps', $data['accepted_steps']);
}
public function applyOn()
@@ -94,36 +90,30 @@ class StepFilterOnDate implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_steps_multi', ChoiceType::class, [
'label' => 'export.filter.course.by_step.steps',
->add('accepted_steps', ChoiceType::class, [
'choices' => self::STEPS,
'multiple' => true,
'multiple' => false,
'expanded' => true,
'empty_data' => self::DEFAULT_CHOICE,
'data' => self::DEFAULT_CHOICE,
])
->add('calc_date', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_calc',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
}
public function getFormDefaultData(): array
{
return [
'accepted_steps_multi' => self::DEFAULT_CHOICE,
'calc_date' => new RollingDate(RollingDate::T_TODAY),
];
}
public function describeAction($data, $format = 'string')
{
$steps = array_map(fn (string $step) => $this->translator->trans(array_flip(self::STEPS)[$step]), $data['accepted_steps_multi']);
$step = array_flip(self::STEPS)[$data['accepted_steps']];
return ['Filtered by steps: only %step%', [
'%step%' => implode(', ', $steps),
'%step%' => $this->translator->trans($step),
]];
}
public function getTitle()
{
return 'export.filter.course.by_step.Filter by step';
return 'Filter by step';
}
}

View File

@@ -1,125 +0,0 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function in_array;
class StepFilterBetweenDates implements FilterInterface
{
private const DEFAULT_CHOICE = [
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private const STEPS = [
'course.draft' => AccompanyingPeriod::STEP_DRAFT,
'course.confirmed' => AccompanyingPeriod::STEP_CONFIRMED,
'course.closed' => AccompanyingPeriod::STEP_CLOSED,
'course.inactive_short' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
'course.inactive_long' => AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
];
private RollingDateConverterInterface $rollingDateConverter;
private TranslatorInterface $translator;
public function __construct(
RollingDateConverterInterface $rollingDateConverter,
TranslatorInterface $translator
) {
$this->rollingDateConverter = $rollingDateConverter;
$this->translator = $translator;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$alias = 'acp_filter_by_step_between_dat_alias';
$steps = 'acp_filter_by_step_between_dat_steps';
$from = 'acp_filter_by_step_between_dat_from';
$to = 'acp_filter_by_step_between_dat_to';
$qb
->andWhere(
$qb->expr()->exists(
"SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodStepHistory::class . " {$alias} " .
"WHERE {$alias}.step IN (:{$steps}) AND OVERLAPSI ({$alias}.startDate, {$alias}.endDate),(:{$from}, :{$to}) = TRUE " .
"AND {$alias}.period = acp"
)
)
->setParameter($from, $this->rollingDateConverter->convert($data['date_from']))
->setParameter($to, $this->rollingDateConverter->convert($data['date_to']))
->setParameter($steps, $data['accepted_steps_multi']);
}
public function applyOn()
{
return Declarations::ACP_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_steps_multi', ChoiceType::class, [
'label' => 'export.filter.course.by_step.steps',
'choices' => self::STEPS,
'multiple' => true,
'expanded' => true,
])
->add('date_from', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_from',
])
->add('date_to', PickRollingDateType::class, [
'label' => 'export.filter.course.by_step.date_to',
]);
}
public function getFormDefaultData(): array
{
return [
'accepted_steps_multi' => self::DEFAULT_CHOICE,
'date_from' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
'date_to' => new RollingDate(RollingDate::T_TODAY),
];
}
public function describeAction($data, $format = 'string')
{
$steps = array_map(fn (string $step) => $this->translator->trans(array_flip(self::STEPS)[$step]), $data['accepted_steps_multi']);
return ['export.filter.course.by_step.Filtered by steps: only %step% and between %date_from% and %date_to%', [
'%step%' => implode(', ', $steps),
'%date_from%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
'%date_to%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
]];
}
public function getTitle()
{
return 'export.filter.course.by_step.Filter by step between dates';
}
}

View File

@@ -27,7 +27,7 @@ final class AccompanyingPeriodNotificationHandler implements NotificationHandler
public function getTemplate(Notification $notification, array $options = []): string
{
return '@ChillPerson/AccompanyingPeriod/showInNotification.html.twig';
return 'ChillPersonBundle:AccompanyingPeriod:showInNotification.html.twig';
}
public function getTemplateData(Notification $notification, array $options = []): array

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Notification\NotificationHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository;
final class AccompanyingPeriodWorkEvaluationDocumentNotificationHandler implements NotificationHandlerInterface
{
private AccompanyingPeriodWorkEvaluationDocumentRepository $accompanyingPeriodWorkEvaluationDocumentRepository;
public function __construct(AccompanyingPeriodWorkEvaluationDocumentRepository $accompanyingPeriodWorkEvaluationDocumentRepository)
{
$this->accompanyingPeriodWorkEvaluationDocumentRepository = $accompanyingPeriodWorkEvaluationDocumentRepository;
}
public function getTemplate(Notification $notification, array $options = []): string
{
return '@ChillPerson/AccompanyingCourseWork/showEvaluationDocumentInNotification.html.twig';
}
public function getTemplateData(Notification $notification, array $options = []): array
{
return [
'notification' => $notification,
'document' => $doc = $this->accompanyingPeriodWorkEvaluationDocumentRepository->find($notification->getRelatedEntityId()),
'evaluation' => $doc?->getAccompanyingPeriodWorkEvaluation(),
];
}
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() === AccompanyingPeriodWorkEvaluationDocument::class;
}
}

View File

@@ -1,46 +0,0 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Notification\NotificationHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
final class AccompanyingPeriodWorkNotificationHandler implements NotificationHandlerInterface
{
private AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository;
public function __construct(AccompanyingPeriodWorkRepository $accompanyingPeriodWorkRepository)
{
$this->accompanyingPeriodWorkRepository = $accompanyingPeriodWorkRepository;
}
public function getTemplate(Notification $notification, array $options = []): string
{
return '@ChillPerson/AccompanyingCourseWork/showInNotification.html.twig';
}
public function getTemplateData(Notification $notification, array $options = []): array
{
return [
'notification' => $notification,
'work' => $this->accompanyingPeriodWorkRepository->find($notification->getRelatedEntityId()),
];
}
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() === AccompanyingPeriodWork::class;
}
}

View File

@@ -122,8 +122,7 @@
<add-evaluation
v-for="e in pickedEvaluations"
v-bind:key="e.key"
v-bind:evaluation="e"
v-bind:docAnchorId="this.docAnchorId">
v-bind:evaluation="e">
</add-evaluation>
<!-- box to add new evaluation -->
@@ -297,21 +296,7 @@
@go-to-generate-workflow="goToGenerateWorkflow"
></list-workflow-modal>
</li>
<li>
<button v-if="AmIRefferer"
class="btn btn-notify"
@click="goToGenerateNotification(false)"
></button>
<template v-else>
<button id="btnGroupNotifyButtons" type="button" class="btn btn-notify dropdown-toggle" :title="$t('notification_send')" data-bs-toggle="dropdown" aria-expanded="false">&nbsp;</button>
<ul class="dropdown-menu" aria-labelledby="btnGroupNotifyButtons">
<li><a class="dropdown-item" @click="goToGenerateNotification(true)">{{ $t('notification_notify_referrer') }}</a></li>
<li><a class="dropdown-item" @click="goToGenerateNotification(false)">{{ $t('notification_notify_any') }}</a></li>
</ul>
</template>
</li>
<li v-if="!isPosting">
<button class="btn btn-save" @click="submit">
{{ $t('action.save') }}
@@ -381,10 +366,7 @@ const i18n = {
no_referrers: "Aucun agent traitant",
choose_referrers: "Choisir des agents traitants",
remove_referrer: "Enlever l'agent",
private_comment: "Commentaire privé",
notification_notify_referrer: "Notifier le référent",
notification_notify_any: "Notifier d'autres utilisateurs",
notification_send: "Envoyer une notification",
private_comment: "Commentaire privé"
}
}
};
@@ -407,7 +389,6 @@ export default {
i18n,
data() {
return {
docAnchorId: null,
isExpanded: false,
editor: ClassicEditor,
showAddObjective: false,
@@ -447,14 +428,7 @@ export default {
},
};
},
beforeMount() {
const urlParams = new URLSearchParams(window.location.search);
this.docAnchorId = urlParams.get('doc_id');
},
mounted() {
this.scrollToElement(this.docAnchorId);
},
computed: {
computed: {
...mapState([
'work',
'resultsForAction',
@@ -467,7 +441,6 @@ export default {
'isPosting',
'errors',
'templatesAvailablesForAction',
'me',
]),
...mapGetters([
'hasResultsForAction',
@@ -525,10 +498,6 @@ export default {
this.$store.commit('setPersonsPickedIds', v);
}
},
AmIRefferer() {
return (!(this.work.accompanyingPeriod.user && this.me
&& (this.work.accompanyingPeriod.user.id !== this.me.id)));
}
},
methods: {
toggleSelect() {
@@ -579,19 +548,6 @@ export default {
return this.$store.dispatch('submit', callback)
.catch(e => { console.log(e); throw e; });
},
goToGenerateNotification(tos) {
console.log('save before leave to notification');
const callback = (data) => {
if (tos === true) {
window.location.assign(`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork&entityId=${this.work.id}&tos[0]=${this.work.accompanyingPeriod.user.id}&returnPath=/fr/person/accompanying-period/${this.work.accompanyingPeriod.id}/work`);
} else {
window.location.assign(`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork&entityId=${this.work.id}&returnPath=/fr/person/accompanying-period/${this.work.accompanyingPeriod.id}/work`);
}
}
return this.$store.dispatch('submit', callback)
.catch(e => {console.log(e); throw e});
},
submit() {
this.$store.dispatch('submit').catch((error) => {
if (error.name === 'ValidationException' || error.name === 'AccessException') {
@@ -603,7 +559,7 @@ export default {
});
},
saveFormOnTheFly(payload) {
// console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
let body = { type: payload.type };
body.name = payload.data.text;
@@ -625,12 +581,6 @@ export default {
this.$toast.open({message: 'An error occurred'});
}
})
},
scrollToElement(docAnchorId) {
const documentEl = document.getElementById(`document_${docAnchorId}`);
if (documentEl) {
documentEl.scrollIntoView({behavior: 'smooth'});
}
}
}
};

View File

@@ -11,7 +11,7 @@
</div>
<div>
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation" :docAnchorId="docAnchorId"></form-evaluation>
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation"></form-evaluation>
<ul class="record_actions">
<li v-if="evaluation.workflows_availables.length > 0">
@@ -85,7 +85,7 @@ export default {
Modal,
ListWorkflowModal,
},
props: ['evaluation', 'docAnchorId'],
props: ['evaluation'],
i18n,
data() {
return {

View File

@@ -79,8 +79,8 @@
<h5>{{ $t('Documents') }} :</h5>
<div class="flex-table">
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="d.id" :class="[parseInt(this.docAnchorId) === d.id ? 'bg-blink' : 'nothing']">
<div :id="`document_${d.id}`" class="item-row">
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="d.id">
<div class="item-row">
<div class="input-group input-group-lg mb-3 row">
<label class="col-sm-3 col-form-label">Titre du document:</label>
<div class="col-sm-9">
@@ -92,7 +92,7 @@
:data-key="i"
@input="onInputDocumentTitle"/>
</div>
</div>
</div>
</div>
<div class="item-row">
<div class="item-col item-meta">
@@ -102,32 +102,27 @@
</div>
<div class="item-row">
<div class="item-col">
<ul class="record_actions">
<li v-if="d.workflows_availables.length > 0">
<list-workflow-modal
:workflows="d.workflows"
:allowCreate="true"
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument"
:relatedEntityId="d.id"
:workflowsAvailables="d.workflows_availables"
:preventDefaultMoveToGenerate="true"
:goToGenerateWorkflowPayload="{doc: d}"
@go-to-generate-workflow="goToGenerateWorkflowEvaluationDocument"
></list-workflow-modal>
</li>
<ul class="record_actions" >
<li v-if="d.workflows_availables.length > 0">
<list-workflow-modal
:workflows="d.workflows"
:allowCreate="true"
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument"
:relatedEntityId="d.id"
:workflowsAvailables="d.workflows_availables"
:preventDefaultMoveToGenerate="true"
:goToGenerateWorkflowPayload="{doc: d}"
@go-to-generate-workflow="goToGenerateWorkflowEvaluationDocument"
></list-workflow-modal>
</li>
<li>
<button
v-if="AmIRefferer"
class="btn btn-notify"
@click="goToGenerateDocumentNotification(d, false)">
</button>
<template v-else>
<button id="btnGroupNotifyButtons" type="button" class="btn btn-notify dropdown-toggle" :title="$t('notification_send')" data-bs-toggle="dropdown" aria-expanded="false">&nbsp;</button>
<ul class="dropdown-menu" aria-labelledby="btnGroupNotifyButtons">
<li><a class="dropdown-item" @click="goToGenerateDocumentNotification(d, true)">{{ $t('notification_notify_referrer') }}</a></li>
<li><a class="dropdown-item" @click="goToGenerateDocumentNotification(d, false)">{{ $t('notification_notify_any') }}</a></li>
</ul>
</template>
<add-async-upload
:buttonTitle="$t('replace')"
:options="asyncUploadOptions"
:btnClasses="{'btn': true, 'btn-edit': true}"
@addDocument="(arg) => replaceDocument(d, arg)"
>
</add-async-upload>
</li>
<li>
<document-action-buttons-group
@@ -138,15 +133,6 @@
@on-stored-object-status-change="onStatusDocumentChanged"
></document-action-buttons-group>
</li>
<li>
<add-async-upload
:buttonTitle="$t('replace')"
:options="asyncUploadOptions"
:btnClasses="{'btn': true, 'btn-edit': true}"
@addDocument="(arg) => replaceDocument(d, arg)"
>
</add-async-upload>
</li>
<li v-if="d.workflows.length === 0">
<a class="btn btn-delete" @click="removeDocument(d)">
</a>
@@ -228,17 +214,14 @@ const i18n = {
template_title: "Nom du template",
browse: "Ajouter un document",
replace: "Remplacer",
download: "Télécharger le fichier existant",
notification_notify_referrer: "Notifier le référent",
notification_notify_any: "Notifier d'autres utilisateurs",
notification_send: "Envoyer une notification",
download: "Télécharger le fichier existant"
}
}
};
export default {
name: "FormEvaluation",
props: ['evaluation', 'docAnchorId'],
props: ['evaluation'],
components: {
ckeditor: CKEditor.component,
PickTemplate,
@@ -277,14 +260,8 @@ export default {
},
computed: {
...mapState([
'isPosting',
'work',
'me',
'isPosting'
]),
AmIRefferer() {
return (!(this.$store.state.work.accompanyingPeriod.user && this.$store.state.me
&& (this.$store.state.work.accompanyingPeriod.user.id !== this.$store.state.me.id)));
},
getTemplatesAvailables() {
return this.$store.getters.getTemplatesAvailablesForEvaluation(this.evaluation.evaluation);
},
@@ -413,18 +390,6 @@ export default {
return this.$store.dispatch('submit', callback)
.catch(e => { console.log(e); throw e; });
},
goToGenerateDocumentNotification(document, tos){
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key);
if (tos === true) {
window.location.assign(`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument&entityId=${document.id}&tos[0]=${this.$store.state.work.accompanyingPeriod.user.id}&returnPath=/fr/person/accompanying-period/work/${evaluation.id}/edit`)
} else {
window.location.assign(`/fr/notification/create?entityClass=Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument&entityId=${document.id}&returnPath=/fr/person/accompanying-period/work/${evaluation.id}/edit`)
}
};
return this.$store.dispatch('submit', callback)
.catch(e => {console.log(e); throw e});
}
},
}
</script>
@@ -437,19 +402,4 @@ export default {
ul.document-upload {
justify-content: flex-start;
}
.bg-blink{
color: #050000;
padding: 10px;
display: inline-block;
border-radius: 5px;
animation: blinkingBackground 2.2s infinite;
animation-iteration-count: 2;
}
@keyframes blinkingBackground{
0% { background-color: #ed776d;}
50% { background-color: #ffffff;}
100% { background-color: #ed776d;}
}
</style>

View File

@@ -35,7 +35,6 @@ const store = createStore({
referrers: window.accompanyingCourseWork.referrers,
isPosting: false,
errors: [],
me: null
},
getters: {
socialAction(state) {
@@ -131,9 +130,6 @@ const store = createStore({
}
},
mutations: {
setWhoAmiI(state, me) {
state.me = me;
},
setEvaluationsPicked(state, evaluations) {
state.evaluationsPicked = evaluations.map((e, index) => {
var k = Object.assign(e, {
@@ -389,19 +385,6 @@ const store = createStore({
},
},
actions: {
getWhoAmI({ commit }) {
let url = `/api/1.0/main/whoami.json`;
window.fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving results for goal', s: response.status, b: response.body };
})
.then(data => {
commit('setWhoAmiI', data);
});
},
updateThirdParty({ commit }, payload) {
commit('updateThirdParty', payload);
},
@@ -531,7 +514,6 @@ store.commit('setEvaluationsPicked', window.accompanyingCourseWork.accompanyingP
store.dispatch('getReachablesResultsForAction');
store.dispatch('getReachablesGoalsForAction');
store.dispatch('getReachablesEvaluationsForAction');
store.dispatch('getWhoAmI');
store.state.evaluationsPicked.forEach(evaluation => {
store.dispatch('fetchTemplatesAvailablesForEvaluation', evaluation.evaluation)

View File

@@ -207,7 +207,7 @@
</template>
<script>
import {dateToISO, ISOToDate} from 'ChillMainAssets/chill/js/date';
import {dateToISO} from 'ChillMainAssets/chill/js/date';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
@@ -262,7 +262,7 @@ export default {
},
birthdate: function () {
if (this.person.birthdate !== null || this.person.birthdate === "undefined") {
return ISOToDate(this.person.birthdate.datetime);
return new Date(this.person.birthdate.datetime);
} else {
return "";
}

View File

@@ -5,8 +5,7 @@
# - displayAction: [true|false] default: false
# - displayFontSmall: [true|false] default: false
#}
<div
class="item-bloc{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<div class="item-bloc{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<div class="item-row">
<h2 class="badge-title">
@@ -112,11 +111,9 @@
</div>
{% if displayContent is not defined or displayContent == 'short' %}
<div
class="item-row column{% if displayFontSmall is defined and displayFontSmall == true %} smallfont{% endif %}">
{% include '@ChillPerson/AccompanyingCourseWork/_objectifs_results_evaluations.html.twig' with {
'displayContent': displayContent,
'onlyone': false
<div class="item-row column{% if displayFontSmall is defined and displayFontSmall == true %} smallfont{% endif %}">
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' with {
'displayContent': displayContent
} %}
</div>
{% endif %}
@@ -124,56 +121,35 @@
{% if displayContent is not defined or displayContent == 'short' %}
<div class="item-row separator">
{% import '@ChillPerson/AccompanyingCourseWork/_macros.html.twig' as macro %}
{% import '@ChillPerson/AccompanyingCourseWork/_macros.html.twig' as macro %}
<div class="item-col item-meta">
{{ macro.metadata(w) }}
</div>
{% if displayAction is defined and displayAction == true %}
<ul class="item-col record_actions">
<li>{{ macro.workflowButton(w) }}</li>
{% if displayNotification is defined and displayNotification == true %}
<li>
<div class="d-grid gap-2 {% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}btn-group{% endif %}" {% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}role="group"{% endif %}>
{% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}
<button id="btnGroupNotifyButtons" type="button" class="btn btn-notify dropdown-toggle" title="{{ 'notification.Notify'|trans }}" data-bs-toggle="dropdown" aria-expanded="false">
</button>
<ul class="dropdown-menu" aria-labelledby="btnGroupNotifyButtons">
<li>
<a class="dropdown-item" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': w.id, 'tos': [accompanyingCourse.user.id]}) }}">{{ 'notification.Notify referrer'|trans }}</a>
</li>
<li>
<a class="dropdown-item" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': w.id}) }}">{{ 'notification.Notify any'|trans }}</a>
</li>
</ul>
{% else %}
<a class="btn btn-notify" title="{{ 'notification.Notify'|trans }}" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': w.id}) }}">
</a>
{% endif %}
</div>
</li>
{% endif %}
<ul class="item-col record_actions">
<li>{{ macro.workflowButton(w) }}</li>
<li>
<a class="btn btn-show" title="{{ 'Show'|trans }}"
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_show', {'id': w.id }) }}"
></a>
</li>
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', w) %}
<li>
<a class="btn btn-show" title="{{ 'Show'|trans }}"
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_show', {'id': w.id }) }}"
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
></a>
</li>
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', w) %}
<li>
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
></a>
</li>
{% endif %}
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_DELETE', w) %}
<li>
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
></a>
</li>
{% endif %}
</ul>
{% endif %}
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_DELETE', w) %}
<li>
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
></a>
</li>
{% endif %}
</ul>
{% endif %}
</div>
{% endif %}
@@ -181,51 +157,47 @@
</div>
{#
# This is for 'long' version of content
# Note: this include is wrapped in a flex-table container.
# We start by closing the flex-table so we can add more.
# At the end we leave the last flex-table open, as it will be closed in the container.
# This is for 'long' version of content
# Note: this include is wrapped in a flex-table container.
# We start by closing the flex-table so we can add more.
# At the end we leave the last flex-table open, as it will be closed in the container.
#}
{% if displayContent is defined and displayContent == 'long' %}
</div>
{% if w.results|length > 0 or w.goals|length > 0 or w.accompanyingPeriodWorkEvaluations|length > 0 %}
<h2 class="chill-blue">{{ 'Dispositifs' }}</h2>
<div class="flex-table">{# new flex-table wrapper #}
<div
class="item-bloc colored{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' with {
'displayContent': displayContent,
'onlyone' : false
} %}
</div>
</div>
{% endif %}
<h2 class="chill-blue">{{ 'Comments'|trans }}</h2>
{% if w.results|length > 0 or w.goals|length > 0 or w.accompanyingPeriodWorkEvaluations|length > 0 %}
<h2 class="chill-blue">{{ 'Dispositifs' }}</h2>
<div class="flex-table">
<div
class="item-bloc no-altern{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<h3 class="chill-beige">Public</h3>
{% if w.note is not empty %}
<blockquote class="chill-user-quote">
{{ w.note|chill_entity_render_box({'metadata': true }) }}
</blockquote>
{% else %}
<span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span>
{% endif %}
</div>
{% if w.privateComment.hasCommentForUser(app.user) %}
<div
class="item-bloc no-altern{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<h3 class="chill-beige">Privé</h3>
<blockquote class="chill-user-quote private-quote">
{{ w.privateComment.commentForUser(app.user)|chill_markdown_to_html }}
</blockquote>
<div class="flex-table">{# new flex-table wrapper #}
<div class="item-bloc colored{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' with {
'displayContent': displayContent
} %}
</div>
</div>
{% endif %}
<h2 class="chill-blue">{{ 'Comments'|trans }}</h2>
<div class="flex-table">
<div class="item-bloc no-altern{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<h3 class="chill-beige">Public</h3>
{% if w.note is not empty %}
<blockquote class="chill-user-quote">
{{ w.note|chill_entity_render_box({'metadata': true }) }}
</blockquote>
{% else %}
<span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span>
{% endif %}
</div>
{% if w.privateComment.hasCommentForUser(app.user) %}
<div class="item-bloc no-altern{% if displayContent is defined %} {{ displayContent }}{% endif %}{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<h3 class="chill-beige">Privé</h3>
<blockquote class="chill-user-quote private-quote">
{{ w.privateComment.commentForUser(app.user)|chill_markdown_to_html }}
</blockquote>
</div>
{% endif %}
{# Here flex-table stay open ! read above #}
{% endif %}
{% endif %}

View File

@@ -1,17 +1,7 @@
{% macro metadata(w, include_notif_counter = true) %}
{% if include_notif_counter == true %}
{% set more = [] %}
{% for e in w.accompanyingPeriodWorkEvaluations %}
{% for d in e.documents %}
{% set more = more|merge([{'relatedEntityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument', 'relatedEntityId': d.id}]) %}
{% endfor %}
{% endfor %}
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id, more) %}
{% if notif_counter.total > 0 %}
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id, more) }}
{% endif %}
{% macro metadata(w) %}
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) %}
{% if notif_counter.total > 0 %}
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) }}
{% endif %}
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
{{ macro.updatedBy(w) }}
@@ -30,4 +20,4 @@
{% endfor %}
{% endfor %}
{{ chill_entity_workflow_list('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id, [], suppEvaluations) }}
{% endmacro %}
{% endmacro %}

View File

@@ -3,7 +3,6 @@
# - displayContent: [short|long] default: short
#}
{% if w.results|length > 0 %}
<table class="obj-res-eval">
<thead>
<th class="obj"><h4 class="title_label">{{ 'accompanying_course_work.goal'|trans }}</h4></th>
@@ -65,11 +64,9 @@
</th>
</thead>
<tbody>
{% if onlyone|default(false) %}
{% for e in w.accompanyingPeriodWorkEvaluations %}
{% if evalId is defined and evalId == e.id %}
<tr>
<td class="eval">
{% for e in w.accompanyingPeriodWorkEvaluations %}
<tr>
<td class="eval">
<ul class="eval_title">
<li>
{{ e.evaluation.title|localize_translatable_string }}
@@ -81,15 +78,13 @@
{% if e.endDate %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<b>{{ e.endDate|format_date('short') }}</b>
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
@@ -97,15 +92,13 @@
{% if e.maxDate %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<b>{{ e.maxDate|format_date('short') }}</b>
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
@@ -114,15 +107,13 @@
{% if e.warningInterval and e.warningInterval.d > 0 %}
<li>
{% set days = (e.warningInterval.d + e.warningInterval.m * 30) %}
<span
class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
@@ -131,166 +122,45 @@
{% if e.timeSpent is not null and e.timeSpent > 0 %}
<li>
{% set minutes = (e.timeSpent / 60) %}
<span
class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span> {{ 'duration.minute'|trans({ '{m}' : minutes }) }}
<span class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span> {{ 'duration.minute'|trans({ '{m}' : minutes }) }}
</li>
{% elseif displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span>
<span class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
</ul>
</li>
</ul>
{% endif %}
{% if displayContent is defined and displayContent == 'long' %}
{% endfor %}
{% if recordAction is defined %}
{{ recordAction }}
{% endif %}
{% else %}
{% for e in w.accompanyingPeriodWorkEvaluations %}
<tr>
<td class="eval">
<ul class="eval_title">
<li>
{{ e.evaluation.title|localize_translatable_string }}
<ul class="columns">
<li>
<span
class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
<b>{{ e.startDate|format_date('short') }}</b>
</li>
{% if e.endDate %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<b>{{ e.endDate|format_date('short') }}</b>
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
{% endif %}
{% if e.maxDate %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<b>{{ e.maxDate|format_date('short') }}</b>
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
{% endif %}
{% if e.warningInterval and e.warningInterval.d > 0 %}
<li>
{% set days = (e.warningInterval.d + e.warningInterval.m * 30) %}
<span
class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
</li>
{% else %}
{% if displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
{% endif %}
{% if e.timeSpent is not null and e.timeSpent > 0 %}
<li>
{% set minutes = (e.timeSpent / 60) %}
<span
class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span> {{ 'duration.minute'|trans({ '{m}' : minutes }) }}
</li>
{% elseif displayContent is defined and displayContent == 'long' %}
<li>
<span
class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
</ul>
</li>
</ul>
{% if recordAction is defined %}
{{ recordAction }}
{% if e.comment is not empty %}
<blockquote class="chill-user-quote">{{ e.comment|chill_entity_render_box }}</blockquote>
{% endif %}
{% if displayContent is defined and displayContent == 'long' %}
{% if e.comment is not empty %}
<blockquote
class="chill-user-quote">{{ e.comment|chill_entity_render_box }}</blockquote>
{% endif %}
{% import "@ChillDocStore/Macro/macro.html.twig" as m %}
{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
{% if e.documents|length > 0 %}
<table class="table table-hover align-middle mt-4 mx-auto">
{% for d in e.documents %}
<tr>
<td class="border-0">{{ d.title }}</td>
<td class="border-0">{{ mm.mimeIcon(d.storedObject.type) }}</td>
<td class="border-0 text-end">
{% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}
<button id="btnGroupNotifyButtons" type="button" class="btn btn-sm btn-notify dropdown-toggle" title="{{ 'notification.Notify'|trans }}"
data-bs-toggle="dropdown" aria-expanded="false">
</button>
<ul class="dropdown-menu" aria-labelledby="btnGroupNotifyButtons">
<li>
<a class="dropdown-item"
href="{{ chill_path_add_return_path('chill_main_notification_create', {
'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument',
'entityId': d.id, 'tos': [accompanyingCourse.user.id]}) }}">{{ 'notification.Notify referrer'|trans }}</a>
</li>
<li>
<a class="dropdown-item"
href="{{ chill_path_add_return_path('chill_main_notification_create', {
'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument',
'entityId': d.id}) }}">{{ 'notification.Notify any'|trans }}</a>
</li>
</ul>
{% else %}
<a class="btn btn-notify btn-sm"
title="{{ 'notification.Notify'|trans }}"
href="{{ chill_path_add_return_path('chill_main_notification_create', {
'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument',
'entityId': d.id }) }}"></a>
{% endif %}
{{ d.storedObject|chill_document_button_group(d.title, is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', w), {'small': true}) }}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<span class="chill-no-data-statement">{{ 'No document found'|trans }}</span>
{% endif %}
{% import "@ChillDocStore/Macro/macro.html.twig" as m %}
{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
{% if e.documents|length > 0 %}
<table class="table mt-4 mx-auto">
{% for d in e.documents %}
<tr class="border-0">
<td class="border-0">{{ d.title }}</td>
<td class="border-0">{{ mm.mimeIcon(d.storedObject.type) }}</td>
<td class="border-0 text-end">{{ d.storedObject|chill_document_button_group(d.title, is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', w), {'small': true}) }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<span class="chill-no-data-statement">{{ 'No document found'|trans }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}

View File

@@ -26,8 +26,7 @@
'displayAction': true,
'displayContent': 'short',
'displayFontSmall': true,
'itemBlocClass': '',
'displayNotification': true
'itemBlocClass': ''
} %}
{% endfor %}
</div>

View File

@@ -27,20 +27,7 @@
'displayContent': 'long',
'itemBlocClass': 'uniq extended',
} %}
<div class="p-3 mt-3">{{ macro.metadata(work, false) }}</div>
</div>
<div class="notification notification-list">
{% set more = [] %}
{% for e in work.accompanyingPeriodWorkEvaluations %}
{% for d in e.documents %}
{% set more = more|merge([{'relatedEntityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument', 'relatedEntityId': d.id}]) %}
{% endfor %}
{% endfor %}
{% set notifications = chill_list_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', work.id, more) %}
{% if notifications is not empty %}
{{ notifications|raw }}
{% endif %}
<div class="p-3 mt-3">{{ macro.metadata(work) }}</div>
</div>
<ul class="record_actions sticky-form-buttons">
@@ -49,25 +36,6 @@
class="btn btn-cancel">{{ 'Back to the list'|trans }}</a>
</li>
<li>{{ macro.workflowButton(work) }}</li>
<li>
<div class="d-grid gap-2 {% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}btn-group{% endif %}" {% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}role="group"{% endif %}>
{% if accompanyingCourse.hasUser and accompanyingCourse.user is not same as(app.user) %}
<button id="btnGroupNotifyButtons" type="button" class="btn btn-notify dropdown-toggle" title="{{ 'notification.Notify'|trans }}" data-bs-toggle="dropdown" aria-expanded="false">
</button>
<ul class="dropdown-menu" aria-labelledby="btnGroupNotifyButtons">
<li>
<a class="dropdown-item" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': work.id, 'tos': [accompanyingCourse.user.id]}) }}">{{ 'notification.Notify referrer'|trans }}</a>
</li>
<li>
<a class="dropdown-item" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': work.id}) }}">{{ 'notification.Notify any'|trans }}</a>
</li>
</ul>
{% else %}
<a class="btn btn-notify" title="{{ 'notification.Notify'|trans }}" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', 'entityId': work.id}) }}">
</a>
{% endif %}
</div>
</li>
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', work) %}
<li>
<a class="btn btn-edit"
@@ -79,8 +47,7 @@
<li>
<a class="btn btn-delete"
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': work.id } ) }}"
title = "{{ 'Delete'|trans }}"
></a>
>{{ 'Delete'|trans }}</a>
</li>
{% endif %}
</ul>

View File

@@ -1,134 +0,0 @@
{% if document is not null %}
{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %}
<div class="flex-table accompanying-course-work">
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_DOCUMENT_SHOW', document) %}
{% set doc = document %}
<div class="item-bloc evaluation-item bg-chill-llight-gray">
<div class="item-row mb-2">
<h1>{{ "Document"|trans }}: {{ doc.title }}</h1>
</div>
<div class="item-row mb-2">
<h2 class="badge-title">
<span class="title_label"></span>
<span class="title_action">
{{ evaluation.accompanyingPeriodWork.socialAction|chill_entity_render_string }}
<ul class="small_in_title columns mt-1">
<li>
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
<b>{{ evaluation.accompanyingPeriodWork.startDate|format_date('short') }}</b>
</li>
{% if evaluation.accompanyingPeriodWork.endDate %}
<li>
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<b>{{ evaluation.accompanyingPeriodWork.endDate|format_date('short') }}</b>
</li>
{% endif %}
</ul>
</span>
</h2>
</div>
<div class="item-row mb-2">
<div class="item-col" style="width: 17%;">
<h4 class="title_label">
{{ 'Participants'|trans }}
</h4>
</div>
<div class="item-col list">
{% for p in evaluation.accompanyingPeriodWork.persons %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
targetEntity: { name: 'person', id: p.id },
action: 'show',
displayBadge: true,
buttonText: p|chill_entity_render_string,
isDead: p.deathdate is not null
} %}
{% endfor %}
</div>
</div>
<div class="item-row column">
<table class="obj-res-eval my-3">
<thead>
<tr>
<th class="eval">
<h4 class="title_label">
{{ 'Évaluation'|trans }}
</h4>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="eval">
<ul class="eval_title">
<li class="my-2">
{{ evaluation.evaluation.title|localize_translatable_string }}
<ul class="columns pt-2">
<li>
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
<b>{{ evaluation.startDate|format_date('short') }}</b>
</li>
{% if evaluation.endDate %}
<li>
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
<b>{{ evaluation.endDate|format_date('short') }}</b>
</li>
{% endif %}
{% if evaluation.maxDate %}
<li>
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
<b>{{ evaluation.maxDate|format_date('short') }}</b>
</li>
{% endif %}
{% if evaluation.warningInterval and evaluation.warningInterval.d > 0 %}
<li>
{% set days = (evaluation.warningInterval.d + evaluation.warningInterval.m * 30) %}
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
</li>
{% endif %}
<li>
{% if evaluation.createdBy is not null %}
<span class="item-key">créé par</span>
<b>{{ evaluation.createdBy.username }}</b>
{% endif %}
{% if evaluation.createdAt is not null %}
<span class="item-key">{{ 'le'|trans }}</span>
<b>{{ evaluation.createdAt|format_date('short') }}</b>
{% endif %}
</li>
</ul>
{% if evaluation.comment %}
<blockquote class="chill-user-quote" style="margin-left: 0;">
{{ evaluation.comment }}
</blockquote>
{% endif %}
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<div class="item-row">
<ul class="record_actions">
<li>
<a class="btn btn-show"
href="{{ path('chill_person_accompanying_period_work_show', { 'id': document.accompanyingPeriodWorkEvaluation.accompanyingPeriodWork.id }) }}"
title="{{ 'See the document'|trans }}"></a>
</li>
</ul>
</div>
</div>
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'This is the minimal period details'|trans ~ ': ' ~ document.id }}<br>
{{ 'You are getting a notification for a period you are not allowed to see'|trans }}
</div>
{% endif %}
</div>
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'You are getting a notification for a period which does not exists any more'|trans }}
</div>
{% endif %}

View File

@@ -1,30 +0,0 @@
{% macro recordAction(work) %}
<li>
<a class="btn btn-show" title="{{ 'Show'|trans }}"
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_show', {'id': work.id }) }}"
></a>
</li>
{% endmacro %}
{% if work is not null %}
<div class="flex-table accompanying-course-work">
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE', work) %}
{% include "@ChillPerson/AccompanyingCourseWork/_item.html.twig" with {
'itemBlocClass': 'bg-chill-llight-gray',
'displayAction': true,
'displayContent': 'short',
'displayFontSmall': true,
'displayNotification:':true,
'w': work
} %}
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'This is the minimal period details'|trans ~ ': ' ~ work.id }}<br>
{{ 'You are getting a notification for a period you are not allowed to see'|trans }}
</div>
{% endif %}
</div>
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'You are getting a notification for a period which does not exists any more'|trans }}
</div>
{% endif %}

View File

@@ -8,7 +8,7 @@
{% if period is not null %}
<div class="flex-table">
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_SEE', period) %}
{% include "@ChillPerson/AccompanyingPeriod/_list_item.html.twig" with {
{% include 'ChillPersonBundle:AccompanyingPeriod:_list_item.html.twig' with {
'recordAction': _self.recordAction(notification.relatedEntityId),
'itemBlocClass': 'bg-chill-llight-gray'
} %}

View File

@@ -17,15 +17,6 @@
<div class="col-md-10">
<h1>{{ 'My accompanying periods'|trans }}</h1>
<ul class="nav nav-pills justify-content-center">
<li class="nav-item">
<a class="nav-link {% if active == true %}active{% endif %}" aria-current="page" href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true}) }}">{{ ['Confirmed'|trans, 'course.inactive_short'|trans, 'course.inactive_long'|trans]|join(', ') }}</a>
</li>
<li class="nav-item ">
<a class="nav-link {% if active == false %}active{% endif %}" href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': false}) }}">{{ 'course.closed'|trans }}</a>
</li>
</ul>
<p>{{ 'Number of periods'|trans }}: <span class="badge rounded-pill bg-primary">{{ pagination.totalItems }}</span></p>
<div class="flex-table accompanyingcourse-list">

View File

@@ -123,7 +123,7 @@
<ul class="record_actions">
<li>{{ doc.storedObject|chill_document_button_group(doc.title, is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork)) }}</li>
<li>
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id, 'doc_id': doc.id}) }}">
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
{{ 'Show'|trans }}
</a>
</li>

View File

@@ -13,7 +13,7 @@ namespace Chill\PersonBundle\Tests\Export\Filter\AccompanyingCourseFilters;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilterOnDate;
use Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilter;
/**
* @internal
@@ -21,7 +21,7 @@ use Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilterOnDate;
*/
final class StepFilterTest extends AbstractFilterTest
{
private StepFilterOnDate $filter;
private StepFilter $filter;
protected function setUp(): void
{

View File

@@ -28,14 +28,11 @@ services:
tags:
- { name: chill.export_filter, alias: accompanyingcourse_socialissue_filter }
Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilterOnDate:
chill.person.export.filter_step:
class: Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilter
tags:
- { name: chill.export_filter, alias: accompanyingcourse_step_filter }
Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\StepFilterBetweenDates:
tags:
- { name: chill.export_filter, alias: accompanyingcourse_step_filter_between_dates }
chill.person.export.filter_geographicalunitstat:
class: Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\GeographicalUnitStatFilter
tags:

View File

@@ -2,9 +2,3 @@ services:
Chill\PersonBundle\Notification\AccompanyingPeriodNotificationHandler:
autowire: true
autoconfigure: true
Chill\PersonBundle\Notification\AccompanyingPeriodWorkNotificationHandler:
autowire: true
autoconfigure: true
Chill\PersonBundle\Notification\AccompanyingPeriodWorkEvaluationDocumentNotificationHandler:
autowire: true
autoconfigure: true

View File

@@ -473,6 +473,7 @@ Accepted socialissues: Problématiques sociales
"Filtered by socialissues: only %socialissues%": "Filtré par problématique sociale: uniquement %socialissues%"
Group by social issue: Grouper les parcours par problématiques sociales
Filter by step: Filtrer les parcours par statut du parcours
Accepted steps: Statuts
Step: Statut
"Filtered by steps: only %step%": "Filtré par statut du parcours: uniquement %step%"
@@ -1084,13 +1085,7 @@ export:
title: Filter les parcours par intervenant
'Filtered by user working on course: only %users%': 'Filtré par intervenants sur le parcours: seulement %users%'
by_step:
Filter by step: Filtrer les parcours par statut du parcours
Filter by step between dates: Filtrer les parcours par statut du parcours entre deux dates
steps: Statuts retenus
date_calc: Date de prise en compte du statut
date_from: Statuts acquis après cette date
date_to: Statuts acquis avant cette date
'Filtered by steps: only %step% and between %date_from% and %date_to%': 'Filtré par statut: seulement %step%, entre %date_from% et %date_to%'
by_user_scope:
Computation date for referrer: Date à laquelle le référent était actif
by_referrer:

View File

@@ -166,7 +166,7 @@ class LoadReports extends AbstractFixture implements ContainerAwareInterface, Or
/**
* pick a random choice.
*
* @return string|string[]
* @return string|string[] the array of slug if multiple, a single slug otherwise
*/
private function getRandomChoice(CustomField $field)
{
@@ -211,8 +211,6 @@ class LoadReports extends AbstractFixture implements ContainerAwareInterface, Or
return $result;
}
}
return $picked;
}
/**
@@ -228,7 +226,7 @@ class LoadReports extends AbstractFixture implements ContainerAwareInterface, Or
/**
* pick a choice within a 'choices' options (for choice type).
*
* @return string the slug of the selected choice
* @return the slug of the selected choice
*/
private function pickChoice(array $choices)
{

View File

@@ -303,6 +303,7 @@ final class SingleTaskController extends AbstractController
$filterOrder->getCheckboxData('status'),
array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
);
$nb = $this->singleTaskAclAwareRepository->countByAllViewable(
$filterOrder->getQueryString(),
$flags
@@ -678,6 +679,7 @@ final class SingleTaskController extends AbstractController
return $this->filterOrderHelperFactory
->create(self::class)
->addSearchBox()
->addPersonPicker('personPicker')
->addCheckbox('status', $statuses, $statuses, $statusTrans)
->addCheckbox('states', $states, ['new', 'in_progress'])
->build();

View File

@@ -27,8 +27,10 @@
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('page_task_list') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('page_task_list') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}

View File

@@ -119,3 +119,5 @@ CHILL_TASK_TASK_UPDATE: Modifier une tâche
CHILL_TASK_TASK_CREATE_FOR_COURSE: Créer une tâche pour un parcours
CHILL_TASK_TASK_CREATE_FOR_PERSON: Créer une tâche pour un usager
filter:
Filter on user: Filtrer par utilisateur/ utilisatrice