Merge branch 'signature-app-master' into 'master'

Signature app master

Closes #307

See merge request Chill-Projet/chill-bundles!743
This commit is contained in:
2024-11-12 20:30:00 +00:00
426 changed files with 22236 additions and 2253 deletions

View File

@@ -300,7 +300,96 @@
</ul>
</div>
<h3><code>slim</code></h3>
<p>Ajouter <code>slim</code> enlève la marge inférieure. Permet un meilleur alignement horizontal dans une <code>row</code></p>
<div class="container">
<div class="row row-hover">
<div class="col-8">
Some text, ul_record_actions sans slim
</div>
<div class="col-4">
<ul class="record_actions">
<li><button class="btn">Some action</button></li>
</ul>
</div>
</div>
<div class="row row-hover">
<div class="col-8">
Some text, ul_record_actions avec slim
</div>
<div class="col-4">
<ul class="record_actions slim">
<li><button class="btn">Some action</button></li>
</ul>
</div>
</div>
</div>
<xmp><a class="btn btn-submit">Text</a></xmp>
Toutes les classes btn-* de bootstrap sont fonctionnelles
<h2>Hover</h2>
<p>Ajouter <code>.row-hover</code> sur une class <code>.row</code> provoque un changement de background au survol</p>
<div class="container">
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-8">
<span class="onthefly-container" data-target-name="person" data-target-id="329" data-action="show" data-button-text="Fatoumata Binta DIALLO (33 ans)" data-display-badge="true" data-v-app=""><a data-v-0c1a1125=""><span data-v-0c1a1125="" class="chill-entity entity-person badge-person">Fatoumata Binta DIALLO (33 ans)<!--v-if--></span></a><!--teleport start--><!--teleport end--></span>
</div>
<div class="col-sm-12 col-md-4">
<span class="text-end">A signé le 04/09/2024 à 13:55</span>
</div>
</div>
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-8">
<span class="onthefly-container" data-target-name="person" data-target-id="330" data-action="show" data-button-text="Abdoulaye DIALLO (9 ans)" data-display-badge="true" data-v-app=""><a data-v-0c1a1125=""><span data-v-0c1a1125="" class="chill-entity entity-person badge-person">Abdoulaye DIALLO (9 ans)<!--v-if--></span></a><!--teleport start--><!--teleport end--></span>
</div>
<div class="col-sm-12 col-md-4">
<ul class="record_actions">
<li>
<a class="btn btn-misc" href="/fr/main/workflow/signature/6/metadata?returnPath=/fr/main/workflow/15/show"><i class="fa fa-pencil-square-o"></i> Signer</a>
</li>
</ul>
</div>
</div>
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-8">
<span class="onthefly-container" data-target-name="person" data-target-id="332" data-action="show" data-button-text="Mohamed DIALLO (44 ans)" data-display-badge="true" data-v-app=""><a data-v-0c1a1125=""><span data-v-0c1a1125="" class="chill-entity entity-person badge-person">Mohamed DIALLO (44 ans)<!--v-if--></span></a><!--teleport start--><!--teleport end--></span>
</div>
<div class="col-sm-12 col-md-4">
<span class="text-end">A signé le 04/09/2024 à 13:57</span>
</div>
</div>
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-8">
<span class="onthefly-container" data-target-name="person" data-target-id="333" data-action="show" data-button-text="Fatou DIALLO (37 ans)" data-display-badge="true" data-v-app=""><a data-v-0c1a1125=""><span data-v-0c1a1125="" class="chill-entity entity-person badge-person">Fatou DIALLO (37 ans)<!--v-if--></span></a><!--teleport start--><!--teleport end--></span>
</div>
<div class="col-sm-12 col-md-4">
<ul class="record_actions">
<li>
<a class="btn btn-misc" href="/fr/main/workflow/signature/8/metadata?returnPath=/fr/main/workflow/15/show"><i class="fa fa-pencil-square-o"></i> Signer</a>
</li>
</ul>
</div>
</div>
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-8">
<span class="onthefly-container" data-target-name="person" data-target-id="334" data-action="show" data-button-text="Fanta DIALLO (7 ans)" data-display-badge="true" data-v-app=""><a data-v-0c1a1125=""><span data-v-0c1a1125="" class="chill-entity entity-person badge-person">Fanta DIALLO (7 ans)<!--v-if--></span></a><!--teleport start--><!--teleport end--></span>
</div>
<div class="col-sm-12 col-md-4">
<ul class="record_actions">
<li>
<a class="btn btn-misc" href="/fr/main/workflow/signature/9/metadata?returnPath=/fr/main/workflow/15/show"><i class="fa fa-pencil-square-o"></i> Signer</a>
</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui-bundle.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '/_dev/specs.yaml',
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
<span class="badge-user-group" style="color: {{ user_group.foregroundColor }}; background-color: {{ user_group.backgroundColor }};">{{ user_group.label|localize_translatable_string }}</span>

View File

@@ -163,6 +163,7 @@
<div class="chill-collection">
<ul class="list-entry"
{{ form.vars.js_caller }}="{{ form.vars.js_caller }}"
data-uniqid="{{ form.vars.uniqid|escape('html_attr') }}"
data-collection-name="{{ form.vars.name|escape('html_attr') }}"
data-collection-identifier="{{ form.vars.identifier|escape('html_attr') }}"
data-collection-button-remove-label="{{ form.vars.button_remove_label|trans|e }}"
@@ -184,6 +185,8 @@
{% if form.vars.allow_add == 1 %}
<button class="add-entry btn btn-misc"
type="button"
data-uniqid="{{ form.vars.uniqid|escape('html_attr') }}"
data-collection-add-target="{{ form.vars.name|escape('html_attr') }}"
data-form-prototype="{{ ('<div>' ~ form_widget(form.vars.prototype) ~ '</div>')|escape('html_attr') }}" >
<i class="fa fa-plus fa-fw"></i>

View File

@@ -60,7 +60,7 @@
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
<a href="#" class="more">{{ app.request.locale | capitalize }}</a>
{{ app.request.locale | capitalize }}
</a>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="menu-languages">

View File

@@ -0,0 +1,21 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block title %}
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
{% endblock %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock admin_content %}

View File

@@ -0,0 +1,86 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% block table_entities %}
<div class="flex-table">
{% for entity in entities %}
<div class="item-bloc">
<div class="item-row">
<div class="wrap-header">
<div class="wh-row">
<div class="wh-col">
{{ entity|chill_entity_render_box }}
</div>
<div class="wh-col">
{%- if not entity.active -%}
<div>
<span class="badge bg-danger">{{ 'user_group.inactive'|trans }}</span>
</div>&nbsp;
{%- endif -%}
<div>{{ 'user_group.with_count_users'|trans({'count': entity.users|length}) }}</div>
</div>
</div>
</div>
</div>
<div class="item-row separator">
<div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
<strong>{{ 'user_group.with_users'|trans }}</strong>
</div>
<div class="wl-col list">
{% for user in entity.userListByLabelAscending %}
<p class="wl-item">
<span class="badge-user">
{{ user|chill_entity_render_box }}
</span>
</p>
{% else %}
<p class="wl-item chill-no-data-statement">{{ 'user_group.no_users'|trans }}</p>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="item-row separator">
<div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
<strong>{{ 'user_group.adminUsers'|trans }}</strong>
</div>
<div class="wl-col list">
{% for user in entity.adminUserListByLabelAscending %}
<p class="wl-item">
<span class="badge-user">
{{ user|chill_entity_render_box }}
</span>
</p>
{% else %}
<p class="wl-item chill-no-data-statement">{{ 'user_group.no_admin_users'|trans }}</p>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="item-row separator">
<ul class="record_actions slim">
<li>
<a href="{{ chill_path_add_return_path('chill_crud_admin_user_group_edit', {'id': entity.id}) }}" class="btn btn-edit"></a>
</li>
</ul>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block actions_before %}
<li class='cancel'>
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans }}</a>
</li>
{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -0,0 +1,160 @@
{% extends '@ChillMain/layout.html.twig' %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
<style type="text/css">
form.remove {
display: inline-block;
padding: 1px;
border: 1px solid transparent;
border-radius: 4px;
}
form:hover {
animation-duration: 0.5s;
animation-name: onHover;
animation-iteration-count: 1;
border: 1px solid #dee2e6;
border-radius: 4px;
}
form.remove button.remove {
display: inline;
background-color: unset;
border: none;
color: var(--bs-chill-red);
}
@keyframes onHover {
from {
border: 1px solid transparent;
}
to {
border: 1px solid #dee2e6;
}
}
</style>
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block title 'user_group.my_groups'|trans %}
{% block content %}
<h1>{{ block('title') }}</h1>
{% if paginator.totalItems == 0 %}
<p>{{ 'user_group.no_user_groups'|trans }}</p>
{% else %}
<div class="flex-table">
{% for entity in groups %}
<div class="item-bloc">
<div class="item-row">
<div class="wrap-header">
<div class="wh-row">
<div class="wh-col">
{{ entity|chill_entity_render_box }}
</div>
<div class="wh-col">
{%- if not entity.active -%}
<div>
<span class="badge bg-danger">{{ 'user_group.inactive'|trans }}</span>
</div>&nbsp;
{%- endif -%}
<div>{{ 'user_group.with_count_users'|trans({'count': entity.users|length}) }}</div>
</div>
</div>
</div>
</div>
<div class="item-row separator">
<div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
<strong>{{ 'user_group.with_users'|trans }}</strong>
</div>
<div class="wl-col list">
{% if entity.users.contains(app.user) %}
{% if is_granted('CHILL_MAIN_USER_GROUP_APPEND_TO_GROUP', entity) %}
<form class="remove" method="POST" action="{{ chill_path_add_return_path('chill_main_user_groups_remove_user', {'id': entity.id, 'userId': app.user.id}) }}">
<p class="wl-item">
{{ 'user_group.me'|trans }}
<button class="remove" type="submit"><i class="fa fa-times"></i></button>
</p>
</form>
{% else %}
<p class="wl-item">
{% if entity.users|length > 1 %}{{ 'user_group.me_and'|trans }}{% else %}{{ 'user_group.me_only'|trans }}{% endif %}
</p>
{% endif %}
{% endif %}
{% for user in entity.userListByLabelAscending %}
{% if user is not same as app.user %}
{% if is_granted('CHILL_MAIN_USER_GROUP_APPEND_TO_GROUP', entity) %}
<form class="remove" method="POST" action="{{ chill_path_add_return_path('chill_main_user_groups_remove_user', {'id': entity.id, 'userId': user.id}) }}">
<p class="wl-item">
<span class="badge-user">
{{ user|chill_entity_render_box }}
</span>
<button class="remove" type="submit"><i class="fa fa-times"></i></button>
</p>
</form>
{% else %}
<p class="wl-item">
<span class="badge-user">
{{ user|chill_entity_render_box }}
</span>
</p>
{% endif %}
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
{% if entity.adminUsers|length > 0 %}
<div class="item-row separator">
<div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
<strong>{{ 'user_group.adminUsers'|trans }}</strong>
</div>
<div class="wl-col list">
{% if entity.adminUsers.contains(app.user) %}
<p class="wl-item">{% if entity.adminUsers|length > 1 %}{{ 'user_group.me_and'|trans }}{% else %}{{ 'user_group.me_only'|trans }}{% endif %}</p>
{% endif %}
{% for user in entity.adminUserListByLabelAscending %}
{% if user is not same as app.user %}
<p class="wl-item">
<span class="badge-user">
{{ user|chill_entity_render_box }}
</span>
</p>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
{% endif -%}
{%- set form = forms.offsetGet(entity) %}
{%- if form is not null -%}
<div class="item-row separator">
<ul class="record_actions slim">
<li>
{{- form_start(form) -}}
{{- form_widget(form.users) -}}
{{- form_end(form) -}}
</li>
</ul>
</div>
{%- endif %}
</div>
{% endfor %}
</div>
{{ chill_pagination(paginator) }}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block title %}
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
{% endblock %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock admin_content %}

View File

@@ -6,7 +6,7 @@
{{ form_errors(transition_form) }}
{% set step = entity_workflow.currentStepChained %}
{% set labels = workflow_metadata(entity_workflow, 'label', step.currentStep) %}
{% set labels = workflow_metadata(entity_workflow, 'label', step.currentStep, entity_workflow.workflowName) %}
{% set label = labels is null ? step.currentStep : labels|localize_translatable_string %}
<div class="card">
@@ -58,24 +58,57 @@
{{ form_row(transition_form.transition) }}
</div>
{% if transition_form.freezeAfter is defined %}
{{ form_row(transition_form.freezeAfter) }}
{% endif %}
<div id="signature-zone">
<div id="signature-type-choice">
{{ form_row(transition_form.isPersonOrUserSignature) }}
{{ form_errors(transition_form.isPersonOrUserSignature) }}
</div>
<div id="user-signature-field">
{{ form_row(transition_form.futureUserSignature) }}
{{ form_errors(transition_form.futureUserSignature) }}
</div>
<div id="person-signature-field">
{{ form_row(transition_form.futurePersonSignatures) }}
{{ form_errors(transition_form.futurePersonSignatures) }}
</div>
</div>
<div id="futureDests">
{{ form_row(transition_form.future_dest_users) }}
<div id="future-dest-users">
{{ form_row(transition_form.futureDestUsers) }}
{{ form_errors(transition_form.futureDestUsers) }}
</div>
<div id="future-cc-users">
{{ form_row(transition_form.futureCcUsers) }}
{{ form_errors(transition_form.futureCcUsers) }}
</div>
</div>
{{ form_row(transition_form.future_cc_users) }}
{{ form_row(transition_form.future_dest_emails) }}
{{ form_errors(transition_form.future_dest_users) }}
<div id="sendExternalContainer">
{{ form_row(transition_form.futureDestineeThirdParties) }}
{{ form_errors(transition_form.futureDestineeThirdParties) }}
{{ form_row(transition_form.futureDestineeEmails) }}
{{ form_errors(transition_form.futureDestineeEmails) }}
</div>
<p>{{ form_label(transition_form.comment) }}</p>
{{ form_widget(transition_form.comment) }}
<ul class="record_actions">
<ul class="record_actions sticky-form-buttons">
{% if entity_workflow.isOnHoldByUser(app.user) %}
<li>
<a class="btn btn-misc" href="{{ path('chill_main_workflow_remove_hold', {'id': entity_workflow.currentStep.id }) }}"><i class="fa fa-hourglass"></i>
{{ 'workflow.Remove hold'|trans }}
</a>
</li>
{% else %}
<li>
<a class="btn btn-misc" href="{{ path('chill_main_workflow_on_hold', {'id': entity_workflow.id}) }}"><i class="fa fa-hourglass"></i>
{{ 'workflow.Put on hold'|trans }}
</a>
</li>
{% endif %}
<li>
<button type="submit" class="btn btn-save">{{ 'Save'|trans }}</button>
</li>
@@ -98,15 +131,6 @@
</ul>
{% endif %}
{% if entity_workflow.currentStep.destEmail|length > 0 %}
<p><b>{{ 'workflow.An access key was also sent to those addresses'|trans }}&nbsp;:</b></p>
<ul>
{% for e in entity_workflow.currentStep.destEmail -%}
<li><a href="mailto:{{ e|escape('html_attr') }}">{{ e }}</a></li>
{%- endfor %}
</ul>
{% endif %}
{% if entity_workflow.currentStep.destUserByAccessKey|length > 0 %}
<p><b>{{ 'workflow.Those users are also granted to apply a transition by using an access key'|trans }}&nbsp;:</b></p>
<ul>

View File

@@ -1,8 +1,5 @@
{% set acl = "0" %}
{% if is_granted('CHILL_MAIN_WORKFLOW_CREATE', blank_workflow) %}
{% set acl = "1" %}
{% endif %}
{% set acl = "1" %}
{# note: the list of available workflows already check that it is possible to create a given workflow #}
{# vue component #}
<div data-list-workflows="1"
data-workflows="{{ entity_workflows_json|json_encode|e('html_attr') }}"

View File

@@ -2,7 +2,7 @@
<div class="flex-table">
{% for step in entity_workflow.stepsChained %}
{% set place_labels = workflow_metadata(entity_workflow, 'label', step.currentStep) %}
{% set place_labels = workflow_metadata(entity_workflow, 'label', step.currentStep, entity_workflow.workflowName) %}
{% set place_label = place_labels is null ? step.currentStep : place_labels|localize_translatable_string %}
<div class="item-bloc {{ 'bloc' ~ step.id }} {% if loop.first %}initial{% endif %}">
@@ -13,38 +13,40 @@
{{ 'workflow.No transitions'|trans }}
</div>
{% else %}
<div class="item-col">
{% if step.previous is not null and step.previous.freezeAfter == true %}
<i class="fa fa-snowflake-o fa-sm me-1" title="{{ 'workflow.Freezed'|trans }}"></i>
{% endif %}
{% if loop.last %}
{% if entity_workflow.isOnHoldAtCurrentStep %}
{% for hold in step.holdsOnStep %}
<span class="badge bg-success rounded-pill" title="{{ 'workflow.On hold by'|trans({'by': hold.byUser|chill_entity_render_string})|escape('html_attr') }}">{{ 'workflow.On hold by'|trans({'by': hold.byUser|chill_entity_render_string}) }}</span>
{% endfor %}
{% endif %}
{% endif %}
</div>
<div class="item-col flex-column align-items-end">
<div class="decided">
{{ place_label }}
</div>
{#
<div class="decided">
<i class="fa fa-times fa-fw text-danger"></i>
Refusé
</div>
#}
</div>
{% endif %}
</div>
{% if step.next is not null %}
{% set transition = chill_workflow_transition_by_string(step.entityWorkflow, step.transitionAfter) %}
{% set transition_labels = workflow_metadata(step.entityWorkflow, 'label', transition) %}
{% set transition_labels = workflow_metadata(step.entityWorkflow, 'label', transition, step.entityWorkflow.workflowName) %}
{% set transition_label = transition_labels is null ? step.transitionAfter : transition_labels|localize_translatable_string %}
{% set forward = workflow_metadata(step.entityWorkflow, 'isForward', transition) %}
{% set forward = workflow_metadata(step.entityWorkflow, 'isForward', transition, step.entityWorkflow.workflowName) %}
<div class="item-row separator">
<div class="item-col" style="width: inherit;">
{% if step.transitionBy is not null %}
<div>
{{ step.transitionBy|chill_entity_render_box({'at_date': step.transitionAt}) }}
{%- if step.transitionBy is not null -%}
<span class="badge-user">{{ step.transitionBy|chill_entity_render_box({'at_date': step.transitionAt}) }}</span>
{% else %}
<span class="chill-no-data-statement">{{ 'workflow.Automated transition'|trans }}</span>
{%- endif -%}
</div>
{% endif %}
<div>
<span>{{ step.transitionAt|format_datetime('long', 'medium') }}</span>
</div>
@@ -69,13 +71,31 @@
</blockquote>
</div>
{% endif %}
{% if loop.last and step.allDestUser|length > 0 %}
{% if not loop.last and step.signatures|length > 0 %}
<div class="separator">
<div>
<p><b>{{ 'workflow.signatures_title'|trans({'nb_signatures': step.signatures|length}) }}&nbsp;:</b></p>
<div>
{{ include('@ChillMain/Workflow/_signature_list.html.twig', {'signatures': step.signatures, is_small: true }) }}
</div>
</div>
</div>
{% endif %}
{% if loop.last and not step.isFinal %}
<div class="item-row separator">
<div>
{% if step.destUser|length > 0 %}
{% if step.destUser|length > 0 or step.destUserGroups|length > 0 %}
<p><b>{{ 'workflow.Users allowed to apply transition'|trans }}&nbsp;: </b></p>
<ul>
{% for u in step.destUser %}
<li>
<span class="badge-user">{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</span>
{% if step.isOnHoldByUser(u) %}
<span class="badge bg-success rounded-pill" title="{{ 'workflow.On hold'|trans|escape('html_attr') }}">{{ 'workflow.On hold'|trans }}</span>
{% endif %}
</li>
{% endfor %}
{% for u in step.destUserGroups %}
<li>{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</li>
{% endfor %}
</ul>
@@ -85,7 +105,7 @@
<p><b>{{ 'workflow.Users put in Cc'|trans }}&nbsp;: </b></p>
<ul>
{% for u in step.ccUser %}
<li>{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</li>
<li><span class="badge-user">{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</span></li>
{% endfor %}
</ul>
{% endif %}
@@ -103,12 +123,23 @@
<p><b>{{ 'workflow.Those users are also granted to apply a transition by using an access key'|trans }}&nbsp;:</b></p>
<ul>
{% for u in step.destUserByAccessKey %}
<li>{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</li>
<li><span class="badge-user">{{ u|chill_entity_render_box({'at_date': step.previous.transitionAt}) }}</span></li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% if step.signatures|length > 0 %}
<p><b>{{ 'workflow.signatures_title'|trans({'nb_signatures': step.signatures|length}) }}&nbsp;:</b></p>
{{ include('@ChillMain/Workflow/_signature_list.html.twig', {'signatures': step.signatures, is_small: true }) }}
{% endif %}
{% endif %}
{% if step.sends|length > 0 %}
<div>
<p><b>{{ 'workflow.sent_through_secured_link'|trans }}</b></p>
{{ include('@ChillMain/Workflow/_send_views_list.html.twig', {'sends': step.sends}) }}
</div>
{% endif %}
</div>

View File

@@ -1,11 +1,15 @@
<h2>
{{ 'workflow_'|trans }}
</h2>
{% if handler is not null %}
<h2>
{{ 'workflow_'|trans }}
</h2>
<div class="item-row col" style="display: block;">
{% include handler.template(entity_workflow) with handler.templateData(entity_workflow)|merge({
'description': true,
'breadcrumb': true,
'add_classes': ''
}) %}
</div>
<div class="item-row col" style="display: block;">
{% include handler.template(entity_workflow) with handler.templateData(entity_workflow)|merge({
'description': true,
'breadcrumb': true,
'add_classes': ''
}) %}
</div>
{% else %}
<h2>{{ 'workflow.deleted_title'|trans }}</h2>
{% endif %}

View File

@@ -0,0 +1,35 @@
<div class="container">
{% for send in sends %}
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-5">
{% 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 %}
<a href="mailto:{{ send.destineeEmail }}">{{ send.destineeEmail }}</a>
{% endif %}
{% if not send.expired %}
<p><small>{{ 'workflow.send_external_message.document_available_until'|trans({'expiration': send.expireAt}) }}</small></p>
{% endif %}
</div>
<div class="col-sm-12 col-md-7 text-end">
<p><small>{{ 'workflow.external_views.number_of_views'|trans({'numberOfViews': send.views|length}) }}</small></p>
{% if send.views|length > 0 %}
<p><small>{{ 'workflow.external_views.last_view_at'|trans({'at': send.lastView.viewAt }) }}</small></p>
<p>
<small>
<b>{{ 'workflow.public_views_by_ip'|trans }}&nbsp;:</b>
{%- for ip, vs in send.viewsByIp -%}
<span title="{% for v in vs %}{{ v.viewAt|format_datetime('short', 'short')|escape('html_attr') }}{% if not loop.last %}{{ ', '|escape('html_attr') }}{% endif %}{% endfor %}">{{ ip }} ({{ vs|length }}x)</span>
{%- endfor -%}
</small>
</p>
{% endif %}
</div>
</div>
{% endfor %}
</div>

View File

@@ -0,0 +1,3 @@
<h2>{{ 'workflow.signature_required_title'|trans({'nb_signatures': signatures|length}) }}</h2>
{{ include('@ChillMain/Workflow/_signature_list.html.twig') }}

View File

@@ -0,0 +1,52 @@
<div class="container">
{% for s in signatures %}
<div class="row row-hover align-items-center">
<div class="col-sm-12 col-md-5">
{% if s.signerKind == 'person' %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: true,
targetEntity: { name: 'person', id: s.signer.id },
buttonText: s.signer|chill_entity_render_string,
isDead: s.signer.deathDate is not null
} %}
{% else %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: true,
targetEntity: { name: 'user', id: s.signer.id },
buttonText: s.signer|chill_entity_render_string,
} %}
{% endif %}
</div>
<div class="col-sm-12 col-md-7 text-end">
{% if s.isSigned %}
<span class="text-end">{{ 'workflow.signature.signed_statement'|trans({ 'datetime' : s.stateDate }) }}</span>
{% elseif s.isCanceled %}
<span class="text-end">{{ 'workflow.signature.canceled_statement'|trans({ 'datetime' : s.stateDate }) }}</span>
{% elseif s.isRejected%}
<span class="text-end">{{ 'workflow.signature.rejected_statement'|trans({ 'datetime' : s.stateDate }) }}</span>
{% else %}
{% if (is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_CANCEL', s) or is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_SIGN', s)) %}
<ul class="record_actions slim {% if is_small|default(false) %}small{% endif %}">
{% if is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_REJECT', s) %}
<li>
<a class="btn btn-remove" href="{{ chill_path_add_return_path('chill_main_workflow_signature_reject', { 'id': s.id}) }}">{{ 'workflow.signature_zone.button_reject'|trans }}</a>
</li>
{% endif %}
{% if is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_CANCEL', s) %}
<li>
<a class="btn btn-misc" href="{{ chill_path_add_return_path('chill_main_workflow_signature_cancel', { 'id': s.id}) }}">{{ 'workflow.signature_zone.button_cancel'|trans }}</a>
</li>
{% endif %}
{% if is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_SIGN', s) %}
<li>
<a class="btn btn-misc" href="{{ chill_path_add_return_path('chill_main_workflow_signature_metadata', { 'signature_id': s.id}) }}"><i class="fa fa-pencil-square-o"></i> {{ 'workflow.signature_zone.button_sign'|trans }}</a>
</li>
{% endif %}
</ul>
{% endif %}
{% endif %}
</div>
</div>
{% endfor %}
</div>

View File

@@ -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') }}
@@ -39,6 +38,9 @@
<h2>{{ handler.entityTitle(entity_workflow) }}</h2>
{{ macro.breadcrumb({'entity_workflow': entity_workflow}) }}
{% if entity_workflow.isOnHoldAtCurrentStep %}
<span class="badge bg-success rounded-pill" title="{{ 'workflow.On hold'|trans|escape('html_attr') }}">{{ 'workflow.On hold'|trans }}</span>
{% endif %}
</div>
{% include handler_template with handler_template_data|merge({'display_action': true }) %}
@@ -57,18 +59,19 @@
</section>
<section class="step my-4">{% include '@ChillMain/Workflow/_follow.html.twig' %}</section>
<section class="step my-4">{% include '@ChillMain/Workflow/_decision.html.twig' %}</section>{#
<section class="step my-4">{% include '@ChillMain/Workflow/_comment.html.twig' %}</section> #}
{% if signatures|length > 0 %}
<section class="step my-4">{% include '@ChillMain/Workflow/_signature.html.twig' %}</section>
{% elseif entity_workflow.currentStep.sends|length > 0 %}
<section class="step my-4">
<h2>{{ 'workflow.external_views.title'|trans({'numberOfSends': entity_workflow.currentStep.sends|length }) }}</h2>
{% include '@ChillMain/Workflow/_send_views_list.html.twig' with {'sends': entity_workflow.currentStep.sends} %}
</section>
{% else %}
<section class="step my-4">{% include '@ChillMain/Workflow/_decision.html.twig' %}</section>
{% endif %}
{# <section class="step my-4">{% include '@ChillMain/Workflow/_comment.html.twig' %}</section> #}
<section class="step my-4">{% include '@ChillMain/Workflow/_history.html.twig' %}</section>
{# useful ?
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a class="btn btn-cancel" href="{{ path('chill_main_workflow_list_dest') }}">
{{ 'Back to the list'|trans }}
</a>
</li>
</ul>
#}
</div>
{% endblock %}

View File

@@ -69,6 +69,9 @@
</button>
<div>
{{ macro.breadcrumb(l) }}
{% if l.entity_workflow.isOnHoldAtCurrentStep %}
<span class="badge bg-success rounded-pill" title="{{ 'workflow.On hold'|trans|escape('html_attr') }}">{{ 'workflow.On hold'|trans }}</span>
{% endif %}
</div>
</div>

View File

@@ -3,24 +3,30 @@
{% if step.previous is not null %}
<li>
<span class="item-key">{{ 'By'|trans ~ ' : ' }}</span>
<b>{{ step.previous.transitionBy|chill_entity_render_box({'at_date': step.previous.transitionAt }) }}</b>
<b>{% if step.previous.transitionBy is not null %}{{ step.previous.transitionBy|chill_entity_render_box({'at_date': step.previous.transitionAt }) }}{% else %}<span class="chill-no-data-statement">{{ 'workflow.Automated transition'|trans }}</span>{% endif %}</b>
</li>
<li>
<span class="item-key">{{ 'Le'|trans ~ ' : ' }}</span>
<b>{{ step.previous.transitionAt|format_datetime('short', 'short') }}</b>
</li>
<li>
<span class="item-key">{{ 'workflow.For'|trans ~ ' : ' }}</span>
<b>
{% for d in step.destUser %}{{ d|chill_entity_render_string({'at_date': step.previous.transitionAt}) }}{% if not loop.last %}, {% endif %}{% endfor %}
</b>
</li>
<li>
<span class="item-key">{{ 'workflow.Cc'|trans ~ ' : ' }}</span>
<b>
{% for u in step.ccUser %}{{ u|chill_entity_render_string({'at_date': step.previous.transitionAt }) }}{% if not loop.last %}, {% endif %}{% endfor %}
</b>
</li>
{% if step.destUser|length > 0 or step.destUserGroups|length > 0 %}
<li>
<span class="item-key">{{ 'workflow.For'|trans ~ ' : ' }}</span>
<b>
{% for d in step.destUser %}<span class="badge-user">{{ d|chill_entity_render_string({'at_date': step.previous.transitionAt}) }}</span>{% if not loop.last %}, {% endif -%}{% endfor -%}
{%- if step.destUser|length > 0 and step.destUserGroups|length > 0 %}, {% endif -%}
{%- for d in step.destUserGroups %}{{ d|chill_entity_render_box }}{% if not loop.last %}, {% endif %}{% endfor -%}
</b>
</li>
{% endif %}
{% if step.ccUser|length > 0 %}
<li>
<span class="item-key">{{ 'workflow.Cc'|trans ~ ' : ' }}</span>
<b>
{% for u in step.ccUser %}{{ u|chill_entity_render_string({'at_date': step.previous.transitionAt }) }}{% if not loop.last %}, {% endif %}{% endfor %}
</b>
</li>
{% endif %}
{% else %}
<li>
<span class="item-key">{{ 'workflow.Created by'|trans ~ ' : ' }}</span>
@@ -40,7 +46,7 @@
{% endif %}
{% if step.previous is not null %}
{% set transition = chill_workflow_transition_by_string(step.entityWorkflow, step.previous.transitionAfter) %}
{% set labels = workflow_metadata(step.entityWorkflow, 'label', transition) %}
{% set labels = workflow_metadata(step.entityWorkflow, 'label', transition, step.entityWorkflow.workflowName) %}
{% set label = labels is null ? step.previous.transitionAfter : labels|localize_translatable_string %}
{{ label }}
{% endif %}
@@ -49,7 +55,7 @@
{% macro breadcrumb(_ctx) %}
<div class="breadcrumb">
{% for step in _ctx.entity_workflow.stepsChained %}
{% set labels = workflow_metadata(_ctx.entity_workflow, 'label', step.currentStep) %}
{% set labels = workflow_metadata(_ctx.entity_workflow, 'label', step.currentStep, _ctx.entity_workflow.workflowName) %}
{% set label = labels is null ? step.currentStep : labels|localize_translatable_string %}
{% set popTitle = _self.popoverTitle(step) %}
{% set popContent = _self.popoverContent(step) %}

View File

@@ -0,0 +1,22 @@
{% extends '@ChillMain/layout.html.twig' %}
{% block title 'workflow.signature_zone.metadata.sign_by'|trans({ '%name%' : person|chill_entity_render_string}) %}
{% block content %}
<div class="col-10 workflow">
<h1 class="mb-5">{{ block('title') }}</h1>
{% if metadata_form is not null %}
{{ form_start(metadata_form) }}
{{ form_row(metadata_form.documentType) }}
{{ form_row(metadata_form.documentNumber) }}
{{ form_row(metadata_form.expirationDate) }}
<ul class="record_actions">
<li>
{{ form_widget(metadata_form.submit, { 'attr' : { 'class' : 'btn btn-submit' }} ) }}
</li>
</ul>
{{ form_end(metadata_form) }}
{% endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="{{ asset('build/images/favicon.ico') }}" type="image/x-icon">
<title>Signature</title>
{{ encore_entry_link_tags('mod_bootstrap') }}
{{ encore_entry_link_tags('mod_forkawesome') }}
{{ encore_entry_link_tags('chill') }}
{{ encore_entry_link_tags('vue_document_signature') }}
</head>
<body>
{% block js %}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
<script type="text/javascript">
window.signature = {{ signature|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_document_signature') }}
{% endblock %}
<div class="content" id="content">
<div class="row">
<div class="col-12 m-auto">
<div class="row" id="document-signature"></div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -8,6 +8,6 @@ Vous êtes invités à valider cette étape au plus tôt.
Vous pouvez visualiser le workflow sur cette page:
{{ absolute_url(path('chill_main_workflow_show', {'id': entity_workflow.id})) }}
{{ absolute_url(path('chill_main_workflow_show', {'id': entity_workflow.id, '_locale': 'fr'})) }}
Cordialement,

View File

@@ -0,0 +1,9 @@
Chers membres du groupe {{ user_group.label|localize_translatable_string }},
Un suivi "{{ workflow.text }}" a atteint une nouvelle étape: {{ place.text }}
Vous pouvez visualiser le workflow sur cette page:
{{ absolute_url(path('chill_main_workflow_grant_access_by_key', {'id': entity_workflow.currentStep.id, '_locale': 'fr', 'accessKey': entity_workflow.currentStep.accessKey})) }}
Cordialement,

View File

@@ -1,15 +0,0 @@
Madame, Monsieur,
Un suivi "{{ workflow.text }}" a atteint une nouvelle étape: {{ workflow.text }}.
Titre du workflow: "{{ entityTitle }}".
Vous êtes invité·e à valider cette étape. Pour obtenir un accès, vous pouvez cliquer sur le lien suivant:
{{ absolute_url(path('chill_main_workflow_grant_access_by_key', {'id': entity_workflow.currentStep.id, 'accessKey': entity_workflow.currentStep.accessKey})) }}
Dès que vous aurez cliqué une fois sur le lien, vous serez autorisé à valider cette étape.
Notez que vous devez disposer d'un compte utilisateur valide dans Chill.
Cordialement,

View File

@@ -1 +0,0 @@
Un suivi {{ workflow.text }} demande votre attention: {{ entityTitle }}

View File

@@ -0,0 +1,88 @@
<!doctype html>
<html>
<body>
{%- set previous = send.entityWorkflowStepChained.previous -%}
{%- if previous.transitionBy is not null -%}
{%- set sender = previous.transitionBy|chill_entity_render_string -%}
{%- else -%}
{%- set sender = 'workflow.send_external_message.sender_system_user'|trans -%}
{%- endif -%}
<script type="application/ld+json">
{%- set data = {
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"url": absolute_url(path('chill_main_workflow_send_view_public', {'uuid': send.uuid, 'verificationKey': send.privateToken})),
"name": 'workflow.send_external_message.see_docs_action_name'|trans
},
"description": 'workflow.send_external_message.see_doc_action_description'|trans({'sender': sender}),
} -%}
{{- data|json_encode|raw -}}
</script>
<div
style='background-color:#F5F5F5;color:#262626;font-family:"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif;font-size:16px;font-weight:400;letter-spacing:0.15008px;line-height:1.5;margin:0;padding:32px 0;min-height:100%;width:100%'
>
<table
align="center"
width="100%"
style="margin:0 auto;max-width:600px;background-color:#FFFFFF"
role="presentation"
cellspacing="0"
cellpadding="0"
border="0"
>
<tbody>
<tr style="width:100%">
<td>
<div style="font-weight:normal;padding:16px 24px 16px 24px">
{{ 'workflow.send_external_message.greeting'|trans }},
</div>
<div style="font-weight:normal;padding:16px 24px 16px 24px">
{{ 'workflow.send_external_message.explanation'|trans({'sender': sender}) }}
</div>
<div style="font-weight:normal;padding:16px 24px 16px 24px">
{{ 'workflow.send_external_message.confidentiality'|trans }}
</div>
<div style="text-align:center;padding:16px 24px 16px 24px">
<a
href="{{ absolute_url(path('chill_main_workflow_send_view_public', {'uuid': send.uuid, 'verificationKey': send.privateToken})) }}"
style="color:#FFFFFF;font-size:16px;font-weight:bold;background-color:#334d5c;border-radius:4px;display:inline-block;padding:12px 20px;text-decoration:none"
target="_blank"
><span
><!--[if mso
]><i
style="letter-spacing: 20px;mso-font-width:-100%;mso-text-raise:30"
hidden
>&nbsp;</i
><!
[endif]--></span
><span>
{{ 'workflow.send_external_message.button_content'|trans({'sender': sender}) }}
</span><span
><!--[if mso
]><i
style="letter-spacing: 20px;mso-font-width:-100%"
hidden
>&nbsp;</i
><!
[endif]--></span
></a
>
</div>
<div style="font-weight:normal;padding:16px 24px 16px 24px">
{{ 'workflow.send_external_message.document_available_until'|trans({ 'expiration': send.expireAt}, null, lang) }}
</div>
<div style="font-weight:normal;padding:16px 24px 16px 24px">
{{ 'workflow.send_external_message.or_see_link'|trans }}&nbsp;:
</div>
<div style="font-size:16px;padding:16px 24px 16px 24px">
<code>{{ absolute_url(path('chill_main_workflow_send_view_public', {'uuid': send.uuid, 'verificationKey': send.privateToken})) }}</code>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ 'workflow.public_link.expired_link_title'|trans }}</title>
</head>
<body>
<h1>{{ 'workflow.public_link.expired_link_title'|trans }}</h1>
<p>{{ 'workflow.public_link.expired_link_explanation'|trans }}</p>
</body>
</html>

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" >
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" >
<title>{% block title %}{% endblock %}</title>
{% block head_custom %}{% endblock %}
<link rel="shortcut icon" href="{{ asset('build/images/favicon.ico') }}" type="image/x-icon">
{{ encore_entry_link_tags('mod_bootstrap') }}
{{ encore_entry_link_tags('mod_forkawesome') }}
{{ encore_entry_link_tags('chill') }}
{% block css %}{% endblock %}
</head>
<body>
<header>
<nav class="navbar navbar-dark bg-primary navbar-expand-md">
<div class="container-xxl">
<div class="col-4">
<a class="navbar-brand" href="{{ path('chill_main_homepage') }}">
{{ include('@ChillMain/Layout/_header-logo.html.twig') }}
</a>
</div>
<div class="col-8"></div>
</div>
</nav>
</header>
<div class="content" id="content">
<div class="container-xxl">
<div class="row justify-content-center my-5">
<div>
{% block public_content %}{% endblock %}
</div>
<div style="margin-top: 1rem;">
<p>
{{ 'workflow.public_link.shared_explanation_until_remaining'|trans({'expireAt': send.expireAt, 'viewsCount': metadata.viewsCount, 'viewsRemaining': metadata.viewsRemaining}) }}
</p>
</div>
</div>
</div>
</div>
{{ include('@ChillMain/Layout/_footer.html.twig', {'public_page': true}) }}
{{ encore_entry_script_tags('mod_bootstrap') }}
{{ encore_entry_script_tags('mod_forkawesome') }}
{{ encore_entry_script_tags('chill') }}
{% block js %}{% endblock %}
</body>
</html>

View File

@@ -0,0 +1,20 @@
{% extends '@ChillMain/layout.html.twig' %}
{% block title %}{{ 'workflow.signature.cancel_signature_of'|trans({ '%signer%': signature.signer|chill_entity_render_string }) }}{% endblock %}
{% block content %}
<h1>{{ block('title') }}</h1>
<p>{{ 'workflow.signature.cancel_are_you_sure'|trans({'%signer%': signature.signer|chill_entity_render_string}) }}</p>
{{ form_start(form) }}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_main_workflow_show', {'id': signature.step.entityWorkflow.id}) }}">{{ 'Cancel'|trans }}</a>
</li>
<li>
{{ form_widget(form.confirm, {'attr': {'class': 'btn btn-misc'}}) }}
</li>
</ul>
{{ form_end(form) }}
{% endblock %}

View File

@@ -0,0 +1,20 @@
{% extends '@ChillMain/layout.html.twig' %}
{% block title %}{{ 'workflow.signature.reject_signature_of'|trans({ '%signer%': signature.signer|chill_entity_render_string }) }}{% endblock %}
{% block content %}
<h1>{{ block('title') }}</h1>
<p>{{ 'workflow.signature.reject_are_you_sure'|trans({'%signer%': signature.signer|chill_entity_render_string}) }}</p>
{{ form_start(form) }}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_main_workflow_show', {'id': signature.step.entityWorkflow.id}) }}">{{ 'Cancel'|trans }}</a>
</li>
<li>
{{ form_widget(form.confirm, {'attr': {'class': 'btn btn-misc'}}) }}
</li>
</ul>
{{ form_end(form) }}
{% endblock %}

View File

@@ -49,19 +49,19 @@
{% for flashMessage in app.session.flashbag.get('success') %}
<div class="alert alert-success flash_message">
<span>{{ flashMessage|raw }}</span>
<span>{{ flashMessage|trans }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('error') %}
<div class="alert alert-danger flash_message">
<span>{{ flashMessage|raw }}</span>
<span>{{ flashMessage|trans }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="alert alert-warning flash_message">
<span>{{ flashMessage|raw }}</span>
<span>{{ flashMessage|trans }}</span>
</div>
{% endfor %}