diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php
index df996b7ad..0454bae69 100644
--- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php
+++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php
@@ -34,6 +34,7 @@ use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
@@ -64,6 +65,8 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
private OnBehalfOfUserHttpClient $userHttpClient;
+ private Security $security;
+
public function __construct(
CalendarRepository $calendarRepository,
CalendarRangeRepository $calendarRangeRepository,
@@ -74,7 +77,8 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
OnBehalfOfUserHttpClient $userHttpClient,
RemoteEventConverter $remoteEventConverter,
TranslatorInterface $translator,
- UrlGeneratorInterface $urlGenerator
+ UrlGeneratorInterface $urlGenerator,
+ Security $security
) {
$this->calendarRepository = $calendarRepository;
$this->calendarRangeRepository = $calendarRangeRepository;
@@ -86,6 +90,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
$this->translator = $translator;
$this->urlGenerator = $urlGenerator;
$this->userHttpClient = $userHttpClient;
+ $this->security = $security;
}
public function countEventsForUser(User $user, DateTimeImmutable $startDate, DateTimeImmutable $endDate): int
@@ -133,6 +138,24 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
public function isReady(): bool
{
+ $user = $this->security->getUser();
+
+ if (!$user instanceof User) {
+ // this is not a user from chill. This is not the role of this class to
+ // restrict access, so we will just say that we do not have to do anything more
+ // here...
+ return true;
+ }
+
+ if (null === $this->mapCalendarToUser->getUserId($user)) {
+ // this user is not mapped with remote calendar. The user will have to wait for
+ // the next calendar subscription iteration
+ $this->logger->debug('mark user ready for msgraph calendar as he does not have any mapping', [
+ 'userId' => $user->getId(),
+ ]);
+ return true;
+ }
+
return $this->tokenStorage->hasToken();
}
diff --git a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php
index 96787a6fc..c538bd107 100644
--- a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php
+++ b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php
@@ -95,6 +95,16 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
return null;
}
+ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
+ {
+ $suggestedUsers = $entityWorkflow->getUsersInvolved();
+
+ $referrer = $this->getRelatedEntity($entityWorkflow)->getCourse()->getUser();
+ $suggestedUsers[spl_object_hash($referrer)] = $referrer;
+
+ return $suggestedUsers;
+ }
+
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillDocStore/AccompanyingCourseDocument/_workflow.html.twig';
diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
index 17b5db75e..0f00a177f 100644
--- a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
+++ b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php
@@ -30,6 +30,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
+use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\TransitionBlocker;
@@ -48,11 +49,13 @@ class WorkflowController extends AbstractController
private Registry $registry;
+ private Security $security;
+
private TranslatorInterface $translator;
private ValidatorInterface $validator;
- public function __construct(EntityWorkflowManager $entityWorkflowManager, EntityWorkflowRepository $entityWorkflowRepository, ValidatorInterface $validator, PaginatorFactory $paginatorFactory, Registry $registry, EntityManagerInterface $entityManager, TranslatorInterface $translator)
+ public function __construct(EntityWorkflowManager $entityWorkflowManager, EntityWorkflowRepository $entityWorkflowRepository, ValidatorInterface $validator, PaginatorFactory $paginatorFactory, Registry $registry, EntityManagerInterface $entityManager, TranslatorInterface $translator, Security $security)
{
$this->entityWorkflowManager = $entityWorkflowManager;
$this->entityWorkflowRepository = $entityWorkflowRepository;
@@ -61,6 +64,7 @@ class WorkflowController extends AbstractController
$this->registry = $registry;
$this->entityManager = $entityManager;
$this->translator = $translator;
+ $this->security = $security;
}
/**
@@ -291,10 +295,18 @@ class WorkflowController extends AbstractController
if (count($workflow->getEnabledTransitions($entityWorkflow)) > 0) {
// possible transition
+
+ $usersInvolved = $entityWorkflow->getUsersInvolved();
+ $currentUserFound = array_search($this->security->getUser(), $usersInvolved, true);
+
+ if (false !== $currentUserFound) {
+ unset($usersInvolved[$currentUserFound]);
+ }
+
$transitionForm = $this->createForm(
WorkflowStepType::class,
$entityWorkflow->getCurrentStep(),
- ['transition' => true, 'entity_workflow' => $entityWorkflow]
+ ['transition' => true, 'entity_workflow' => $entityWorkflow, 'suggested_users' => $usersInvolved]
);
$transitionForm->handleRequest($request);
diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
index c448ea19e..e4683f24b 100644
--- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
+++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php
@@ -348,6 +348,23 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
return $this->transitionningStep;
}
+ /**
+ * @return User[]
+ */
+ public function getUsersInvolved(): array
+ {
+ $usersInvolved = [];
+ $usersInvolved[spl_object_hash($this->getCreatedBy())] = $this->getCreatedBy();
+
+ foreach ($this->steps as $step) {
+ foreach ($step->getDestUser() as $u) {
+ $usersInvolved[spl_object_hash($u)] = $u;
+ }
+ }
+
+ return $usersInvolved;
+ }
+
public function getWorkflowName(): string
{
return $this->workflowName;
diff --git a/src/Bundle/ChillMainBundle/Form/Type/CommentType.php b/src/Bundle/ChillMainBundle/Form/Type/CommentType.php
index 9b8fc4701..542a429c6 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/CommentType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/CommentType.php
@@ -56,12 +56,7 @@ class CommentType extends AbstractType
public function buildView(FormView $view, FormInterface $form, array $options)
{
- $view->vars = array_replace(
- $view->vars,
- [
- 'fullWidth' => true,
- ]
- );
+ $view->vars['fullWidth'] = true;
}
public function configureOptions(OptionsResolver $resolver)
diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php
index 2fbfdcf11..f6c2b7f4a 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php
@@ -19,6 +19,7 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
@@ -28,12 +29,15 @@ class PickUserDynamicType extends AbstractType
{
private DenormalizerInterface $denormalizer;
+ private NormalizerInterface $normalizer;
+
private SerializerInterface $serializer;
- public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
+ public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
{
$this->denormalizer = $denormalizer;
$this->serializer = $serializer;
+ $this->normalizer = $normalizer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -46,6 +50,11 @@ class PickUserDynamicType extends AbstractType
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['user'];
$view->vars['uniqid'] = uniqid('pick_user_dyn');
+ $view->vars['suggested'] = [];
+
+ foreach ($options['suggested'] as $user) {
+ $view->vars['suggested'][] = $this->normalizer->normalize($user, 'json', ['groups' => 'read']);
+ }
}
public function configureOptions(OptionsResolver $resolver)
@@ -53,7 +62,8 @@ class PickUserDynamicType extends AbstractType
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
- ->setDefault('compound', false);
+ ->setDefault('compound', false)
+ ->setDefault('suggested', []);
}
public function getBlockPrefix()
diff --git a/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php b/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php
index 2ab318d9c..5c29f4d42 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/PrivateCommentType.php
@@ -39,7 +39,7 @@ class PrivateCommentType extends AbstractType
$builder
->add('comments', ChillTextareaType::class, [
'disable_editor' => $options['disable_editor'],
- 'label' => false,
+ 'label' => $options['label'],
])
->setDataMapper($this->dataMapper);
}
diff --git a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php
index f65677dc7..79ed6df40 100644
--- a/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php
+++ b/src/Bundle/ChillMainBundle/Form/Type/ScopePickerType.php
@@ -95,12 +95,7 @@ class ScopePickerType extends AbstractType
public function buildView(FormView $view, FormInterface $form, array $options)
{
- $view->vars = array_replace(
- $view->vars,
- [
- 'fullWidth' => true,
- ]
- );
+ $view->vars['fullWidth'] = true;
}
public function configureOptions(OptionsResolver $resolver)
diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
index a82c61fdc..1b18b3ef8 100644
--- a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
+++ b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php
@@ -154,6 +154,7 @@ class WorkflowStepType extends AbstractType
'label' => 'workflow.dest for next steps',
'multiple' => true,
'mapped' => false,
+ 'suggested' => $options['suggested_users'],
])
->add('future_dest_emails', ChillCollectionType::class, [
'label' => 'workflow.dest by email',
@@ -200,6 +201,7 @@ class WorkflowStepType extends AbstractType
->setAllowedTypes('transition', 'bool')
->setRequired('entity_workflow')
->setAllowedTypes('entity_workflow', EntityWorkflow::class)
+ ->setDefault('suggested_users', [])
->setDefault('constraints', [
new Callback(
function ($step, ExecutionContextInterface $context, $payload) {
diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js
index 890929c35..6b143a11d 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js
+++ b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js
@@ -23,7 +23,7 @@ function loadDynamicPicker(element) {
(input.value === '[]' || input.value === '') ?
null : [ JSON.parse(input.value) ]
)
- ;
+ suggested = JSON.parse(el.dataset.suggested)
if (!isMultiple) {
if (input.value === '[]'){
@@ -37,6 +37,7 @@ function loadDynamicPicker(element) {
':types="types" ' +
':picked="picked" ' +
':uniqid="uniqid" ' +
+ ':suggested="notPickedSuggested" ' +
'@addNewEntity="addNewEntity" ' +
'@removeEntity="removeEntity">',
components: {
@@ -48,16 +49,31 @@ function loadDynamicPicker(element) {
types: JSON.parse(el.dataset.types),
picked: picked === null ? [] : picked,
uniqid: el.dataset.uniqid,
+ suggested: suggested
}
},
+ computed: {
+ notPickedSuggested() {
+ if (this.multiple) {
+ const pickedIds = new Set();
+ for (const p of this.picked) {
+ pickedIds.add(`${p.type}${p.id}`);
+ }
+ return this.suggested.filter(e => !pickedIds.has(`${e.type}${e.id}`))
+ }
+
+ return this.suggested.filter(e => e.type !== this.picked.type && e.id !== e.picked.id);
+ }
+ },
methods: {
- addNewEntity(entity) {
+ addNewEntity({entity}) {
if (this.multiple) {
if (!this.picked.some(el => {
return el.type === entity.type && el.id === entity.id;
})) {
this.picked.push(entity);
input.value = JSON.stringify(this.picked);
+ console.log(entity)
}
} else {
if (!this.picked.some(el => {
@@ -69,7 +85,10 @@ function loadDynamicPicker(element) {
}
}
},
- removeEntity(entity) {
+ removeEntity({entity}) {
+ if (-1 === this.suggested.findIndex(e => e.type === entity.type && e.id === entity.id)) {
+ this.suggested.push(entity);
+ }
this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id));
input.value = JSON.stringify(this.picked);
},
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue
index e121ca950..0a39718e2 100644
--- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue
@@ -17,6 +17,9 @@
+
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/bootstrap5/bootstrap_5_horizontal_layout.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/bootstrap5/bootstrap_5_horizontal_layout.html.twig
index f4a2c3294..1afdbb2c9 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Form/bootstrap5/bootstrap_5_horizontal_layout.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Form/bootstrap5/bootstrap_5_horizontal_layout.html.twig
@@ -68,7 +68,8 @@
{{- form_errors(form) -}}
{% else %}
-
+
{{- form_label(form) -}}
+
{{- form_widget(form, widget_attr) -}}
{{- form_help(form) -}}
{{- form_errors(form) -}}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
index 15d7625dd..28c55c9c1 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
@@ -18,43 +18,48 @@
{% block form_row %}
{% apply spaceless %}
- {% if form.vars.fullWidth is not defined or form.vars.fullWidth == false %}
-
+ {% if attr.class is not defined or ('cf-title' not in attr.class and 'cf-fields' not in attr.class ) %}
+ {{ form_label(form) }}
{% endif %}
- {% endapply %}">
- {% if attr.class is not defined or ('cf-title' not in attr.class and 'cf-fields' not in attr.class ) %}
- {{ form_label(form) }}
+
+
+ {{ form_widget(form) }}
+ {{ form_errors(form) }}
+
+ {% else %}
+
{{ form_label(form) }}
+
{{ form_widget(form) }}
{% endif %}
-
-
- {{ form_widget(form) }}
- {{ form_errors(form) }}
-
- {% else %}
- {{ form_widget(form) }}
- {% endif %}
{% endapply %}
{% endblock form_row %}
+{#
+ The block 'form_row' above may be removed !
+ Read this note: https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/502#note_1311993084
+#}
{% block choice_widget_expanded %}
{% apply spaceless %}
@@ -200,7 +205,6 @@
{% block private_comment_row %}
- {{ form_label(form) }}
{{ form_row(form) }}
{% endblock %}
@@ -211,7 +215,6 @@
{% endblock %}
{% block comment_row %}
- {{ form_label(form) }}
{{ form_row(form) }}
{% endblock %}
@@ -249,7 +252,11 @@
{% block pick_entity_dynamic_widget %}
-
+
{% endblock %}
{% block pick_postal_code_widget %}
@@ -269,4 +276,4 @@
{{ form_errors(form.fixedDate) }}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php
index 5058fed7c..73e260c37 100644
--- a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php
+++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php
@@ -36,6 +36,11 @@ interface EntityWorkflowHandlerInterface
*/
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string;
+ /**
+ * @return User[]
+ */
+ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array;
+
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string;
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array;
diff --git a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml
index 4756ff4f7..263a57049 100644
--- a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml
+++ b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml
@@ -45,3 +45,12 @@ workflow:
few {# workflows}
other {# workflows}
}
+
+duration:
+ minute: >-
+ {m, plural,
+ =0 {Aucune durée}
+ one {# minute}
+ few {# minutes}
+ other {# minutes}
+ }
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php
index 078ef0c3c..8780f7d17 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkEvaluation.php
@@ -160,6 +160,14 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
*/
private ?DateInterval $warningInterval = null;
+ /**
+ * @ORM\Column(type="integer", nullable=true)
+ * @Serializer\Groups({"read", "docgen:read"})
+ * @Serializer\Groups({"write"})
+ * @Serializer\Groups({"accompanying_period_work_evaluation:create"})
+ */
+ private ?int $timeSpent = null;
+
public function __construct()
{
$this->documents = new ArrayCollection();
@@ -265,6 +273,11 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
return $this->warningInterval;
}
+ public function getTimeSpent(): ?int
+ {
+ return $this->timeSpent;
+ }
+
public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
$this->documents->removeElement($document);
@@ -322,6 +335,13 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
return $this;
}
+ public function setTimeSpent(?int $timeSpent): self
+ {
+ $this->timeSpent = $timeSpent;
+
+ return $this;
+ }
+
public function setEvaluation(?Evaluation $evaluation): AccompanyingPeriodWorkEvaluation
{
if (
diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
index e7d1e5dfd..010618733 100644
--- a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
+++ b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
@@ -47,6 +47,7 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
'endDate',
'maxDate',
'warningInterval',
+ 'timeSpent',
'acpw_id',
'acpw_startDate',
'acpw_endDate',
@@ -295,6 +296,9 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
$qb->addSelect(sprintf('workeval.%s AS %s', $field, $field));
}
+ // add the time spent field
+ $qb->addSelect('(workeval.timeSpent / 60) AS timeSpent');
+
// those with identity
foreach (['createdBy', 'updatedBy'] as $field) {
$qb->addSelect(sprintf('IDENTITY(workeval.%s) AS %s', $field, $field));
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php
index efc005be0..a59220d74 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/SocialWorkTypeFilter.php
@@ -19,7 +19,6 @@ use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Doctrine\ORM\EntityManagerInterface;
-use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
@@ -52,45 +51,39 @@ class SocialWorkTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
- $where = $qb->getDQLPart('where');
-
if (count($data['actionType']) > 0) {
- $clause = $qb->expr()->in('acpw.socialAction', ':actionType');
-
- if ($where instanceof Andx) {
- $where->add($clause);
- } else {
- $where = $qb->expr()->andX($clause);
- }
-
- $qb->setParameter('actionType', $data['actionType']);
+ $qb
+ ->andWhere($qb->expr()->in('acpw.socialAction', ':actionType'))
+ ->setParameter('actionType', $data['actionType']);
}
if (count($data['goal']) > 0) {
- if (!in_array('goal', $qb->getAllAliases(), true)) {
- $qb->join('acpw.goals', 'goal');
+ if (!in_array('acpw_goal', $qb->getAllAliases(), true)) {
+ $qb->join('acpw.goals', 'acpw_goal');
}
- $where->add(
- $qb->expr()->in('goal.id', ':goals')
- );
+ $orX = $qb->expr()->orX();
+ foreach ($data['goal'] as $goal) {
- $qb->setParameter('goals', $data['goal']);
- }
+ /** @var Goal $goal */
+ $andX = $qb->expr()->andX();
+ $andX->add($qb->expr()->eq('acpw_goal.goal', $goalId = ':goal_'.uniqid()));
+ $qb->setParameter($goalId, $goal);
- if (count($data['result']) > 0) {
- if (!in_array('result', $qb->getAllAliases(), true)) {
- $qb->join('acpw.results', 'result');
+ if (count($data['result']) > 0) {
+ $orXResult = $qb->expr()->orX();
+ foreach ($data['result'] as $result) {
+
+ /** @var Result $result */
+ $orXResult->add($qb->expr()->isMemberOf($resultId = ':result_'.uniqid(), 'acpw_goal.results'));
+ $qb->setParameter($resultId, $result);
+ }
+ $andX->add($orXResult);
+ }
+ $orX->add($andX);
}
-
- $where->add(
- $qb->expr()->in('result.id', ':results')
- );
-
- $qb->setParameter('results', $data['result']);
+ $qb->andWhere($orX);
}
-
- $qb->add('where', $where);
}
public function applyOn(): string
diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php
index b0be9dd27..76891a74d 100644
--- a/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php
+++ b/src/Bundle/ChillPersonBundle/Form/Type/PickPersonDynamicType.php
@@ -18,21 +18,25 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
- * Pick user dymically, using vuejs module "AddPerson".
+ * m* Pick user dymically, using vuejs module "AddPerson".
*/
class PickPersonDynamicType extends AbstractType
{
private DenormalizerInterface $denormalizer;
+ private DenormalizerInterface $normalizer;
+
private SerializerInterface $serializer;
- public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
+ public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
{
$this->denormalizer = $denormalizer;
$this->serializer = $serializer;
+ $this->normalizer = $normalizer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -45,6 +49,11 @@ class PickPersonDynamicType extends AbstractType
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['person'];
$view->vars['uniqid'] = uniqid('pick_user_dyn');
+ $view->vars['suggested'] = [];
+
+ foreach ($options['suggested'] as $person) {
+ $view->vars['suggested'][] = $this->normalizer->normalize($person, 'json', ['groups' => 'read']);
+ }
}
public function configureOptions(OptionsResolver $resolver)
@@ -52,7 +61,8 @@ class PickPersonDynamicType extends AbstractType
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
- ->setDefault('compound', false);
+ ->setDefault('compound', false)
+ ->setDefault('suggested', []);
}
public function getBlockPrefix()
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue
index d6e42f743..7dcb595a3 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue
@@ -49,6 +49,20 @@
+
+
+ {{ $t('evaluation_time_spent') }}
+
+
+
+ {{ $t('select_time_spent') }}
+
+ {{ time.text }}
+
+
+
+
+
{{ $t('evaluation_public_comment') }}
@@ -191,6 +205,8 @@ const i18n = {
evaluation_choose_a_template: "Choisir un modèle",
evaluation_add_a_document: "Ajouter un document",
evaluation_add: "Ajouter une évaluation",
+ evaluation_time_spent: "Temps de rédaction",
+ select_time_spent: "Indiquez le temps de rédaction",
Documents: "Documents",
document_add: "Générer ou téléverser un document",
document_upload: "Téléverser un document",
@@ -224,6 +240,22 @@ export default {
maxPostSize: 15000000,
required: false,
},
+ timeSpentChoices: [
+ { text: '1 minute', value: 60 }, { text: '2 minutes', value: 120 },
+ { text: '3 minutes', value: 180 }, { text: '4 minutes', value: 240 },
+ { text: '5 minutes', value: 300 }, { text: '10 minutes', value: 600 },
+ { text: '15 minutes', value: 900 },{ text: '20 minutes', value: 1200 },
+ { text: '25 minutes', value: 1500 }, { text: '30 minutes', value: 1800 },
+ { text: '45 minutes', value: 2700 },{ text: '1 hour', value: 3600 },
+ { text: '1 hour 15 minutes', value: 4500 }, { text: '1 hour 30 minutes', value: 5400 },
+ { text: '1 hour 45 minutes', value: 6300 }, { text: '2 hours', value: 7200 },
+ { text: '2 hours 30 minutes', value: 9000 }, { text: '3 hours', value: 10800 },
+ { text: '3 hours 30 minutes', value: 12600 },{ text: '4 hours', value: 14400 },
+ { text: '4 hours 30 minutes', value: 16200 },{ text: '5 hours', value: 18000 },
+ { text: '5 hours 30 minutes', value: 19800 },{ text: '6 hours', value: 21600 },
+ { text: '6 hours 30 minutes', value: 23400 },{ text: '7 hours', value: 25200 },
+ { text: '7 hours 30 minutes', value: 27000 },{ text: '8 hours', value: 28800 },
+ ]
}
},
computed: {
@@ -265,6 +297,10 @@ export default {
get() { return this.evaluation.warningInterval; },
set(v) { this.$store.commit('setEvaluationWarningInterval', { key: this.evaluation.key, days: v }); }
},
+ timeSpent: {
+ get() { return this.evaluation.timeSpent },
+ set(v) { this.$store.commit('setEvaluationTimeSpent', { key: this.evaluation.key, time: v}) }
+ },
comment: {
get() { return this.evaluation.comment; },
set(v) { this.$store.commit('setEvaluationComment', { key: this.evaluation.key, comment: v }); }
diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js
index d9f317b4c..e075e65bc 100644
--- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js
+++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js
@@ -116,6 +116,7 @@ const store = createStore({
endDate: e.endDate === null || e.endDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.endDate)) },
maxDate: e.maxDate === null || e.maxDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.maxDate)) },
warningInterval: intervalDaysToISO(e.warningInterval),
+ timeSpent: e.timeSpent,
comment: e.comment,
documents: e.documents
};
@@ -138,6 +139,7 @@ const store = createStore({
endDate: e.endDate !== null ? dateToISO(new Date(e.endDate.datetime)) : null,
maxDate: e.maxDate !== null ? dateToISO(new Date(e.maxDate.datetime)) : null,
warningInterval: e.warningInterval !== null ? intervalISOToDays(e.warningInterval) : null,
+ timeSpent: e.timeSpent !== null ? e.timeSpent : null,
documents: e.documents.map((d, docIndex) => {
return Object.assign(d, {
key: docIndex
@@ -258,6 +260,7 @@ const store = createStore({
endDate: null,
maxDate: null,
warningInterval: null,
+ timeSpent: null,
comment: "",
editEvaluation: true,
workflows_availables: state.work.workflows_availables_evaluation,
@@ -286,6 +289,10 @@ const store = createStore({
state.evaluationsPicked.find(e => e.key === key)
.warningInterval = days;
},
+ setEvaluationTimeSpent(state, {key, time}) {
+ state.evaluationsPicked.find(e => e.key === key)
+ .timeSpent = time;
+ },
setEvaluationComment(state, {key, comment}) {
state.evaluationsPicked.find(e => e.key === key)
.comment = comment;
@@ -482,7 +489,7 @@ const store = createStore({
;
commit('setIsPosting', true);
- console.log('payload', payload);
+ console.log('the social action', payload);
return makeFetch('PUT', url, payload)
.then(data => {
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_objectifs_results_evaluations.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_objectifs_results_evaluations.html.twig
index 0dd0cc84a..f4198a5c7 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_objectifs_results_evaluations.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_objectifs_results_evaluations.html.twig
@@ -118,6 +118,18 @@
{% endif %}
{% endif %}
+
+ {% if e.timeSpent is not null and e.timeSpent > 0 %}
+
+ {% set minutes = (e.timeSpent / 60) %}
+ {{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }} {{ 'duration.minute'|trans({ '{m}' : minutes }) }}
+
+ {% elseif displayContent is defined and displayContent == 'long' %}
+
+ {{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}
+ {{ 'Not given'|trans }}
+
+ {% endif %}
@@ -143,7 +155,7 @@
{% else %}
{{ 'No document found'|trans }}
{% endif %}
-
+
{% endif %}
diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php
index 735463fc2..500daab6f 100644
--- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php
+++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php
@@ -97,6 +97,21 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
return AccompanyingPeriodWorkEvaluationDocumentVoter::SEE;
}
+ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
+ {
+ $suggestedUsers = $entityWorkflow->getUsersInvolved();
+
+ $referrer = $this->getRelatedEntity($entityWorkflow)
+ ->getAccompanyingPeriodWorkEvaluation()
+ ->getAccompanyingPeriodWork()
+ ->getAccompanyingPeriod()
+ ->getUser();
+
+ $suggestedUsers[spl_object_hash($referrer)] = $referrer;
+
+ return $suggestedUsers;
+ }
+
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_evaluation_document.html.twig';
diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php
index 25edce03b..db67ef045 100644
--- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php
+++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php
@@ -87,6 +87,20 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
return AccompanyingPeriodWorkEvaluationVoter::SEE;
}
+ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
+ {
+ $suggestedUsers = $entityWorkflow->getUsersInvolved();
+
+ $referrer = $this->getRelatedEntity($entityWorkflow)
+ ->getAccompanyingPeriodWork()
+ ->getAccompanyingPeriod()
+ ->getUser();
+
+ $suggestedUsers[spl_object_hash($referrer)] = $referrer;
+
+ return $suggestedUsers;
+ }
+
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_evaluation.html.twig';
diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php
index b6829ab77..75ad04cfb 100644
--- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php
+++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php
@@ -94,6 +94,19 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
return null;
}
+ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
+ {
+ $suggestedUsers = $entityWorkflow->getUsersInvolved();
+
+ $referrer = $this->getRelatedEntity($entityWorkflow)
+ ->getAccompanyingPeriod()
+ ->getUser();
+
+ $suggestedUsers[spl_object_hash($referrer)] = $referrer;
+
+ return $suggestedUsers;
+ }
+
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_accompanying_period_work.html.twig';
diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20230210104424.php b/src/Bundle/ChillPersonBundle/migrations/Version20230210104424.php
new file mode 100644
index 000000000..ec802a993
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/migrations/Version20230210104424.php
@@ -0,0 +1,26 @@
+addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation ADD timeSpent INT DEFAULT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation DROP timeSpent');
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
index 808ce5257..090f35c1c 100644
--- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
@@ -908,6 +908,7 @@ accompanying_course_work:
remove: Supprimer une action d'accompagnement
social_evaluation: Évaluation
private_comment: Commentaire privé
+ timeSpent: Temps de rédaction
#
@@ -1139,6 +1140,7 @@ export:
updatedAt: Date de modification
createdBy: Créé par
updatedBy: Modifié par
+ timeSpent: Temps de rédaction (minutes)
acpw:
List of accompanying period works: Liste des actions
List description: Génère une liste des actions d'accompagnement, filtrée sur différents paramètres.
diff --git a/src/Bundle/ChillThirdPartyBundle/Form/Type/PickThirdpartyDynamicType.php b/src/Bundle/ChillThirdPartyBundle/Form/Type/PickThirdpartyDynamicType.php
index ada4064eb..eb9e7e5ea 100644
--- a/src/Bundle/ChillThirdPartyBundle/Form/Type/PickThirdpartyDynamicType.php
+++ b/src/Bundle/ChillThirdPartyBundle/Form/Type/PickThirdpartyDynamicType.php
@@ -18,6 +18,7 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
+use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
@@ -27,12 +28,15 @@ class PickThirdpartyDynamicType extends AbstractType
{
private DenormalizerInterface $denormalizer;
+ private NormalizerInterface $normalizer;
+
private SerializerInterface $serializer;
- public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
+ public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
{
$this->denormalizer = $denormalizer;
$this->serializer = $serializer;
+ $this->normalizer = $normalizer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -45,6 +49,11 @@ class PickThirdpartyDynamicType extends AbstractType
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['thirdparty'];
$view->vars['uniqid'] = uniqid('pick_user_dyn');
+ $view->vars['suggested'] = [];
+
+ foreach ($options['suggested'] as $tp) {
+ $view->vars['suggested'][] = $this->normalizer->normalize($tp, 'json', ['groups' => 'read']);
+ }
}
public function configureOptions(OptionsResolver $resolver)
@@ -52,7 +61,8 @@ class PickThirdpartyDynamicType extends AbstractType
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
- ->setDefault('compound', false);
+ ->setDefault('compound', false)
+ ->setDefault('suggested', []);
}
public function getBlockPrefix()
diff --git a/src/Bundle/ChillWopiBundle/src/Controller/Editor.php b/src/Bundle/ChillWopiBundle/src/Controller/Editor.php
index b0ff7fb4c..ab4276ec4 100644
--- a/src/Bundle/ChillWopiBundle/src/Controller/Editor.php
+++ b/src/Bundle/ChillWopiBundle/src/Controller/Editor.php
@@ -20,6 +20,7 @@ use Chill\WopiBundle\Service\Controller\ResponderInterface;
use Exception;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use loophp\psr17\Psr17Interface;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -81,7 +82,7 @@ final class Editor
$this->router = $router;
}
- public function __invoke(string $fileId): Response
+ public function __invoke(string $fileId, Request $request): Response
{
if (null === $user = $this->security->getUser()) {
throw new AccessDeniedHttpException('Please authenticate to access this feature');
@@ -151,6 +152,7 @@ final class Editor
UrlGeneratorInterface::ABSOLUTE_URL
),
'closebutton' => 1,
+ 'lang' => $request->getLocale(),
]
)
);
diff --git a/src/Bundle/ChillWopiBundle/src/Resources/views/Editor/page.html.twig b/src/Bundle/ChillWopiBundle/src/Resources/views/Editor/page.html.twig
index 6534dfd30..c96833aa1 100644
--- a/src/Bundle/ChillWopiBundle/src/Resources/views/Editor/page.html.twig
+++ b/src/Bundle/ChillWopiBundle/src/Resources/views/Editor/page.html.twig
@@ -25,6 +25,7 @@