diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSend.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSend.php index f3294bd55..528107561 100644 --- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSend.php +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflowSend.php @@ -183,8 +183,45 @@ class EntityWorkflowSend implements TrackCreationInterface return $this->views->count() > 0; } - public function isExpired(\DateTimeImmutable $now): bool + public function isExpired(?\DateTimeImmutable $now = null): bool { - return $now >= $this->expireAt; + return ($now ?? new \DateTimeImmutable('now')) >= $this->expireAt; + } + + /** + * Retrieves the most recent view. + * + * @return EntityWorkflowSendView|null returns the last view or null if there are no views + */ + public function getLastView(): ?EntityWorkflowSendView + { + $last = null; + foreach ($this->views as $view) { + if (null === $last) { + $last = $view; + } else { + if ($view->getViewAt() > $last->getViewAt()) { + $last = $view; + } + } + } + + return $last; + } + + /** + * Retrieves an array of views grouped by their remote IP address. + * + * @return array> an associative array where the keys are IP addresses and the values are arrays of views associated with those IPs + */ + public function getViewsByIp(): array + { + $views = []; + + foreach ($this->getViews() as $view) { + $views[$view->getRemoteIp()][] = $view; + } + + return $views; } } diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig index d6e5e3216..5fcc60ed4 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_history.html.twig @@ -134,6 +134,13 @@ {{ include('@ChillMain/Workflow/_signature_list.html.twig', {'signatures': step.signatures, is_small: true }) }} {% endif %} {% endif %} + {% if step.sends|length > 0 %} +
+

{{ 'workflow.sent_through_secured_link'|trans }}

+ + {{ include('@ChillMain/Workflow/_send_views_list.html.twig', {'sends': step.sends}) }} +
+ {% endif %} {% endfor %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_send_views_list.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_send_views_list.html.twig new file mode 100644 index 000000000..f0caf4849 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_send_views_list.html.twig @@ -0,0 +1,35 @@ +
+ {% for send in sends %} +
+
+ {% if send.destineeKind == 'thirdParty' %} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'thirdParty', id: send.destineeThirdParty.id }, + buttonText: send.destineeThirdParty|chill_entity_render_string, + } %} + {% else %} + {{ send.destineeEmail }} + {% endif %} + {% if not send.expired %} +

{{ 'workflow.send_external_message.document_available_until'|trans({'expiration': send.expireAt}) }}

+ {% endif %} +
+
+

{{ 'workflow.external_views.number_of_views'|trans({'numberOfViews': send.views|length}) }}

+ {% if send.views|length > 0 %} +

{{ 'workflow.external_views.last_view_at'|trans({'at': send.lastView.viewAt }) }}

+

+ + {{ 'workflow.public_views_by_ip'|trans }} : + {%- for ip, vs in send.viewsByIp -%} + {{ ip }} ({{ vs|length }}x) + {%- endfor -%} + +

+ + {% endif %} +
+
+ {% endfor %} +
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig index 4decb6fec..0fe55e3f2 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/index.html.twig @@ -1,12 +1,11 @@ {% extends '@ChillMain/layout.html.twig' %} -{% block title %} +{% block title -%} {{ 'Workflow'|trans }} -{% endblock %} +{%- endblock %} {% block js %} {{ parent() }} - {{ encore_entry_script_tags('mod_async_upload') }} {{ encore_entry_script_tags('mod_pickentity_type') }} {{ encore_entry_script_tags('mod_entity_workflow_subscribe') }} {{ encore_entry_script_tags('page_workflow_show') }} diff --git a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml index 19f923bdf..0b0d8d65d 100644 --- a/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml +++ b/src/Bundle/ChillMainBundle/translations/messages+intl-icu.fr.yaml @@ -69,6 +69,14 @@ workflow: } send_external_message: document_available_until: Le lien sera valable jusqu'au {expiration, date, long} à {expiration, time, short}. + external_views: + last_view_at: Dernière vue le {at, date, long} à {at, time, short} + number_of_views: >- + {numberOfViews, plural, + =0 {Le partage n'a jamais été visualisé} + =1 {Le partage a été visualisé une fois} + other {Le partage a été visualisé # fois} + } public_link: shared_explanation_until_remaining: >- Ce partage sera actif jusqu'au {expireAt, time, short} à {expireAt, time, short}. {viewsCount, plural, diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 259561844..67992a60f 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -564,14 +564,13 @@ workflow: transition_destinee_add_emails: Ajouter une adresse de courriel transition_destinee_remove_emails: Supprimer transition_destinee_emails_help: Le lien sécurisé sera envoyé à chaque adresse indiquée + sent_through_secured_link: Envoi par lien sécurisé + public_views_by_ip: Visualisation par adresse IP public_link: expired_link_title: Lien expiré expired_link_explanation: Le lien a expiré, vous ne pouvez plus visualiser ce document. - - - signature_zone: title: Signatures électroniques button_sign: Signer