mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'features/thirdparty-improve-acl-collection'
This commit is contained in:
commit
a27b228a6f
28
CHANGELOG.md
28
CHANGELOG.md
@ -10,8 +10,21 @@ and this project adheres to
|
||||
|
||||
## Unreleased
|
||||
|
||||
* add 3 new fields to PostalCode and adapt postal code command and fixtures
|
||||
|
||||
* [Aside activity] Fixes for aside activity
|
||||
|
||||
* categories with child
|
||||
* fast creation buttons
|
||||
* add ordering for types
|
||||
|
||||
* [ThirdParty]:
|
||||
|
||||
* third party list
|
||||
* create a kind contact/institution when create a new thirdparty, and set contact embedded as kind=child;
|
||||
* filter thirdparties in list
|
||||
|
||||
* [FilterOrder]: add development kit for generating filter and ordering in list
|
||||
|
||||
## Test releases
|
||||
|
||||
@ -26,14 +39,21 @@ and this project adheres to
|
||||
|
||||
* a badge "requestor" is shown into search results;
|
||||
* periods where the person is only requestor (without participating) are also shown;
|
||||
|
||||
|
||||
Issues:
|
||||
|
||||
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/13
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/199
|
||||
* [Person form] "accept sms" not required:
|
||||
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/37
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/221
|
||||
* On-The-Fly modale works for showing, editing and creating person and thirdparty ;
|
||||
* AccompanyingCourse Resume page: list associated persons by household, see household when hover, and show on-the-fly modale when clicking on person ;
|
||||
|
||||
* [On-The-Fly] modale works for showing, editing and creating person or thirdparty ;
|
||||
* [AccompanyingCourse Resume page]
|
||||
* associated persons list, can see household when hover, and with show on-the-fly modale when clicking person ;
|
||||
* badge-title for AccompanyingCourseWork and for Activities;
|
||||
* Improve badges behaviour with small screens;
|
||||
|
||||
## Test release yyyy-mm-dd
|
||||
|
||||
|
@ -27,3 +27,4 @@ Version 1.5.5
|
||||
=============
|
||||
|
||||
- [activity] replace dropdown for selecting reasons and use chillEntity for reason rendering
|
||||
- fix bug: error when trying to edit activity of which the type has been deactivated
|
||||
|
@ -174,6 +174,10 @@ class ActivityController extends AbstractController
|
||||
$activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->find($activityType_id);
|
||||
|
||||
if (isset($activityType) && !$activityType->isActive()) {
|
||||
throw new \InvalidArgumentException('Activity type must be active');
|
||||
}
|
||||
|
||||
$activityData = null;
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
|
@ -93,15 +93,13 @@ class ActivityType extends AbstractType
|
||||
/** @var \Chill\ActivityBundle\Entity\ActivityType $activityType */
|
||||
$activityType = $options['activityType'];
|
||||
|
||||
if (!$activityType->isActive()) {
|
||||
throw new \InvalidArgumentException('Activity type must be active');
|
||||
}
|
||||
|
||||
// TODO revoir la gestion des center au niveau du form des activité.
|
||||
if ($options['center']) {
|
||||
$builder->add('scope', ScopePickerType::class, [
|
||||
'center' => $options['center'],
|
||||
'role' => $options['role']
|
||||
'role' => $options['role'],
|
||||
// TODO make required again once scope and rights are fixed
|
||||
'required' => false
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
// Access to Bootstrap variables and mixins
|
||||
@import '~ChillMainAssets/module/bootstrap/shared';
|
||||
|
||||
// activity creation first step: select type page
|
||||
//// ACTIVITY CREATION
|
||||
// first step: select type page
|
||||
|
||||
div.new-activity-select-type {
|
||||
div.activity-row {
|
||||
display: flex;
|
||||
@ -21,91 +23,36 @@ div.new-activity-select-type {
|
||||
}
|
||||
}
|
||||
|
||||
// exceptions for flex-table in list-records
|
||||
div.activity-list {
|
||||
div.flex-table {
|
||||
div.item-bloc {
|
||||
div.item-row.main {
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-basis: 15%;
|
||||
}
|
||||
ul.list-content {
|
||||
li.social-issues, li.social-actions {
|
||||
.badge-primary {
|
||||
font-variant: small-caps;
|
||||
font-weight: bold;
|
||||
font-size: 88%;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
li.social-issues .badge-primary {
|
||||
background-color: $orange;
|
||||
}
|
||||
li.social-actions .badge-primary {
|
||||
background-color: $green;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div.item-row.comment {
|
||||
margin-left: 15%;
|
||||
blockquote.chill-user-quote {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
div.item-row.details {
|
||||
margin-left: 15%;
|
||||
//// ACTIVITY LIST PAGE
|
||||
// precise badge-title specific details
|
||||
|
||||
// override flex-bloc to adapt in list
|
||||
// TODO refund this
|
||||
div.accompanyingCourse.flex-bloc.concerned-groups {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
div.item-bloc {
|
||||
box-shadow: unset;
|
||||
padding: 0;
|
||||
flex-basis: 25%;
|
||||
div.item-row {
|
||||
flex-direction: column;
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
width: unset;
|
||||
}
|
||||
&:last-child {
|
||||
border-top: 0;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
ul.list-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
h2.badge-title {
|
||||
div.duration {
|
||||
font-size: smaller;
|
||||
padding-left: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
ul.list-content {
|
||||
font-size: 70%;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
// exception: change bg color for action badges above badge-title
|
||||
.bg-light {
|
||||
background-color: $chill-light-gray !important;
|
||||
}
|
||||
|
||||
}
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
padding-left: 1em;
|
||||
margin: 0 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.duration {
|
||||
font-size: smaller;
|
||||
padding-left: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div.main {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
// exceptions for flex-bloc in concerned-groups
|
||||
//// ACTIVITY SHOW AND FORM PAGES
|
||||
// Exceptions for flex-bloc in concerned-groups
|
||||
|
||||
div.flex-bloc.concerned-groups {
|
||||
margin-top: 1em;
|
||||
div.item-bloc {
|
||||
@ -130,7 +77,6 @@ div.flex-bloc.concerned-groups {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// CHILL ENTITY RENDER BOX
|
||||
.chill-entity {
|
||||
|
||||
|
@ -0,0 +1,88 @@
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label">
|
||||
|
||||
{% if activity.date %}
|
||||
<h3>{{ activity.date|format_date('short') }}</h3>
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
{% if activity.durationTime and t.durationTimeVisible %}
|
||||
<p>
|
||||
<abbr class="fa fa-fw fa-hourglass-end" title="{{ 'Duration Time'|trans }}"></abbr>
|
||||
{{ activity.durationTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if activity.travelTime and t.travelTimeVisible %}
|
||||
<p>
|
||||
<abbr class="fa fa-fw fa-car" title="{{ 'Travel time'|trans }}"></abbr>
|
||||
{{ activity.travelTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</span>
|
||||
<span class="title_action">
|
||||
|
||||
{{ activity.type.name | localize_translatable_string }}
|
||||
|
||||
<ul class="small_in_title">
|
||||
<li>
|
||||
<abbr title="{{ 'location'|trans }}">{{ 'location'|trans ~ ': ' }}</abbr>
|
||||
{# TODO {% if activity.location %}{{ activity.location }}{% endif %} #}
|
||||
Domicile de l'usager
|
||||
</li>
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<abbr title="{{ 'Referrer'|trans }}">{{ 'Referrer'|trans ~ ': ' }}</abbr>
|
||||
{{ activity.user.usernameCanonical }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<ul class="list-content">
|
||||
{%- if t.reasonsVisible -%}
|
||||
{%- if activity.reasons is not empty -%}
|
||||
<li class="reasons">
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- if t.socialIssuesVisible %}
|
||||
{%- if activity.socialIssues is not empty -%}
|
||||
<li class="social-issues">
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- if t.socialActionsVisible -%}
|
||||
{%- if activity.socialActions is not empty -%}
|
||||
<li class="social-actions">
|
||||
{% for r in activity.socialActions %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
{#
|
||||
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
title="{{ 'Period number %number%'|trans({'%number%': activity.accompanyingPeriod.id}) }}"
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}"><i class="fa fa-random"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
#}
|
@ -5,17 +5,17 @@
|
||||
|
||||
{% if context == 'person' %}
|
||||
{% set blocs = [
|
||||
{ 'title': 'Others persons'|trans,
|
||||
{ 'title': 'Others persons'|trans,
|
||||
'items': entity.persons,
|
||||
'path' : 'chill_person_view',
|
||||
'key' : 'person_id'
|
||||
},
|
||||
{ 'title': 'Third parties'|trans,
|
||||
{ 'title': 'Third parties'|trans,
|
||||
'items': entity.thirdParties,
|
||||
'path' : 'chill_3party_3party_show',
|
||||
'key' : 'thirdparty_id'
|
||||
},
|
||||
{ 'title': 'Users concerned'|trans,
|
||||
{ 'title': 'Users concerned'|trans,
|
||||
'items': entity.users,
|
||||
'path' : 'admin_user_show',
|
||||
'key' : 'id'
|
||||
@ -23,22 +23,22 @@
|
||||
] %}
|
||||
{% else %}
|
||||
{% set blocs = [
|
||||
{ 'title': 'Persons in accompanying course'|trans,
|
||||
{ 'title': 'Persons in accompanying course'|trans,
|
||||
'items': entity.personsAssociated,
|
||||
'path' : 'chill_person_view',
|
||||
'key' : 'person_id'
|
||||
},
|
||||
{ 'title': 'Third persons'|trans,
|
||||
{ 'title': 'Third persons'|trans,
|
||||
'items': entity.personsNotAssociated,
|
||||
'path' : 'chill_person_view',
|
||||
'key' : 'person_id'
|
||||
},
|
||||
{ 'title': 'Third parties'|trans,
|
||||
{ 'title': 'Third parties'|trans,
|
||||
'items': entity.thirdParties,
|
||||
'path' : 'chill_3party_3party_show',
|
||||
'key' : 'thirdparty_id'
|
||||
},
|
||||
{ 'title': 'Users concerned'|trans,
|
||||
{ 'title': 'Users concerned'|trans,
|
||||
'items': entity.users,
|
||||
'path' : 'admin_user_show',
|
||||
'key' : 'id'
|
||||
@ -101,3 +101,31 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if (with_display == 'wrap-list') %}
|
||||
<div class="concerned-groups wrap-list">
|
||||
{% for bloc in blocs %}
|
||||
<div class="wl-row">
|
||||
{% if bloc.items|length > 0 %}
|
||||
<div class="wl-col title">
|
||||
<h4>{{ bloc.title }}</h4>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% for item in bloc.items %}
|
||||
|
||||
<span class="wl-item {% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="activity-list context-{{ context }}">
|
||||
<div class="context-{{ context }}">
|
||||
|
||||
{% if activities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
@ -7,176 +7,56 @@
|
||||
</p>
|
||||
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
<div class="flex-table activity-list">
|
||||
{% for activity in activities %}
|
||||
{% set t = activity.type %}
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
{% if activity.date %}
|
||||
<h3>{{ activity.date|format_date('long') }}</h3>
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
{% if activity.durationTime and t.durationTimeVisible %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ activity.durationTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if activity.travelTime and t.travelTimeVisible %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-car"></i>
|
||||
{{ activity.travelTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
title="{{ 'Period number %number%'|trans({'%number%': activity.accompanyingPeriod.id}) }}"
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}"><i class="fa fa-random"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
|
||||
<div class="float-button top">
|
||||
<div class="box">
|
||||
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-show "></a>
|
||||
</li>
|
||||
{% if no_action is not defined or no_action == false %}
|
||||
{# TODO
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-update "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
|
||||
class="btn btn-sm btn-delete "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
#}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="list-content">
|
||||
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
|
||||
<b>{{ activity.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<b>{{ activity.type.name | localize_translatable_string }}</b>
|
||||
|
||||
{% if activity.attendee is not null and t.attendeeVisible %}
|
||||
{% if activity.attendee %}
|
||||
{{ '→ ' ~ 'present'|trans|capitalize }}
|
||||
{% else %}
|
||||
{{ '→ ' ~ 'not present'|trans|capitalize }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>{{ 'location'|trans ~ ': ' }}</b>
|
||||
Domicile de l'usager
|
||||
|
||||
{# TODO {% if activity.location %}{{ activity.location }}{% endif %}
|
||||
#}
|
||||
|
||||
</li>
|
||||
|
||||
{%- if t.reasonsVisible -%}
|
||||
<li>
|
||||
{%- if activity.reasons is not empty -%}
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialIssuesVisible %}
|
||||
<li class="social-issues">
|
||||
{%- if activity.socialIssues is not empty -%}
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialActionsVisible -%}
|
||||
<li class="social-actions">
|
||||
{%- if activity.socialActions is not empty -%}
|
||||
{% for r in activity.socialActions %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="item-row">
|
||||
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %}
|
||||
</div>
|
||||
|
||||
|
||||
{% if activity.comment.comment is not empty
|
||||
or activity.persons|length > 0
|
||||
or activity.thirdParties|length > 0
|
||||
or activity.users|length > 0
|
||||
%}
|
||||
<div class="item-row comment separator">
|
||||
{% if activity.comment.comment is not empty %}
|
||||
{{ activity.comment|chill_entity_render_box({
|
||||
'disable_markdown': false,
|
||||
'limit_lines': 3,
|
||||
'metadata': false,
|
||||
}) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="item-row details">
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
|
||||
'context': context,
|
||||
'with_display': 'bloc',
|
||||
'entity': activity,
|
||||
'badge_person': true
|
||||
} %}
|
||||
</div>
|
||||
<div class="main">
|
||||
{% if activity.comment.comment is not empty %}
|
||||
{{ activity.comment|chill_entity_render_box({
|
||||
'disable_markdown': false,
|
||||
'limit_lines': 3,
|
||||
'metadata': false,
|
||||
}) }}
|
||||
{% endif %}
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
|
||||
'context': context,
|
||||
'with_display': 'row',
|
||||
'entity': activity,
|
||||
'badge_person': true
|
||||
} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="item-row separator">
|
||||
<div class="updatedBy"></div>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-show "></a>
|
||||
</li>
|
||||
{% if no_action is not defined or no_action == false %}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-update "></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
|
||||
class="btn btn-sm btn-delete "></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
@ -0,0 +1,10 @@
|
||||
<div class="activity-list">
|
||||
{% for activity in activities | slice(0,5) %}
|
||||
{% set t = activity.type %}
|
||||
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"></a>
|
||||
|
||||
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %}
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
@ -73,7 +73,7 @@
|
||||
{% endif %}
|
||||
|
||||
{% if t.travelTimeVisible %}
|
||||
<dt class="inline">{{ 'Travel Time'|trans }}</dt>
|
||||
<dt class="inline">{{ 'Travel time'|trans }}</dt>
|
||||
<dd>{% if entity.travelTime is not null %}
|
||||
{{ entity.travelTime|date('H:i') }}
|
||||
{% else %}
|
||||
|
@ -210,3 +210,5 @@ Group by reasons: Sujet d'activité
|
||||
Aggregate by activity user: Aggréger par utilisateur lié à l'activité
|
||||
Aggregate by activity type: Aggréger par type d'activité
|
||||
Aggregate by activity reason: Aggréger par sujet de l'activité
|
||||
|
||||
Last activities: Les dernières activités
|
||||
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
|
||||
/**
|
||||
* Controller for activity configuration
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
|
||||
public function redirectToAdminIndexAction()
|
||||
{
|
||||
return $this->redirectToRoute('chill_main_admin_central');
|
||||
}
|
||||
}
|
@ -3,6 +3,9 @@
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
|
||||
/**
|
||||
@ -10,5 +13,12 @@ use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
*/
|
||||
class AsideActivityCategoryController extends CRUDController
|
||||
{
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var QueryBuilder $query */
|
||||
$query->addOrderBy('e.ordering', 'ASC');
|
||||
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
@ -12,12 +15,21 @@ use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
final class AsideActivityController extends CRUDController
|
||||
{
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
|
||||
private $categoryRepository;
|
||||
|
||||
public function __construct(AsideActivityCategoryRepository $categoryRepository)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request);
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
}
|
||||
|
||||
protected function buildQueryEntities(string $action, Request $request, ?FilterOrderHelper $filterOrder = null)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request, $filterOrder);
|
||||
|
||||
if ('index' === $action) {
|
||||
$qb->andWhere($qb->expr()->eq('e.agent', ':user'));
|
||||
$qb->where($qb->expr()->eq('e.agent', ':user'));
|
||||
$qb->orWhere($qb->expr()->eq('e.createdBy', ':user'));
|
||||
$qb->setParameter('user', $this->getUser());
|
||||
}
|
||||
|
||||
@ -37,5 +49,24 @@ final class AsideActivityController extends CRUDController
|
||||
return parent::orderQuery($action, $query, $request, $paginator);
|
||||
}
|
||||
|
||||
public function createEntity(string $action, Request $request): object
|
||||
{
|
||||
$asideActivity = new AsideActivity();
|
||||
|
||||
$duration = $request->query->get('duration', '300');
|
||||
$duration = \DateTime::createFromFormat('U', $duration);
|
||||
$asideActivity->setDuration($duration);
|
||||
|
||||
$categoryId = $request->query->get('type', 7);
|
||||
if($categoryId === null){
|
||||
return $this->createNotFoundException('You must give a valid category id');
|
||||
}
|
||||
$category = $this->categoryRepository->find($categoryId);
|
||||
$asideActivity->setType($category);
|
||||
|
||||
$note = $request->query->get('note', null);
|
||||
$asideActivity->setNote($note);
|
||||
|
||||
return $asideActivity;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,12 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$container->setParameter('chill_aside_activity.form.time_duration', $config['form']['time_duration']);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
|
||||
$loader->load('services.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
@ -81,7 +87,7 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
'controller' => \Chill\AsideActivityBundle\Controller\AsideActivityController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'template' => '@ChillAsideActivity/asideActivity/list.html.twig',
|
||||
'template' => '@ChillAsideActivity/asideActivity/index.html.twig',
|
||||
'role' => 'ROLE_USER'
|
||||
],
|
||||
'new' => [
|
||||
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('chill_aside_activity');
|
||||
|
||||
$treeBuilder->getRootNode('chill_aside_activity')
|
||||
->children()
|
||||
->arrayNode('form')
|
||||
->canBeEnabled()
|
||||
->children()
|
||||
->arrayNode('time_duration')
|
||||
->isRequired()
|
||||
->defaultValue(
|
||||
[
|
||||
[ 'label' => '5 minutes', 'seconds' => 300],
|
||||
[ 'label' => '10 minutes', 'seconds' => 600],
|
||||
[ 'label' => '15 minutes', 'seconds' => 900],
|
||||
[ 'label' => '20 minutes', 'seconds' => 1200],
|
||||
[ 'label' => '25 minutes', 'seconds' => 1500],
|
||||
[ 'label' => '30 minutes', 'seconds' => 1800],
|
||||
[ 'label' => '45 minutes', 'seconds' => 2700],
|
||||
[ 'label' => '1 hour', 'seconds' => 3600],
|
||||
[ 'label' => '1 hour 15', 'seconds' => 4500],
|
||||
[ 'label' => '1 hour 30', 'seconds' => 5400],
|
||||
[ 'label' => '1 hour 45', 'seconds' => 6300],
|
||||
[ 'label' => '2 hours', 'seconds' => 7200],
|
||||
[ 'label' => '2 hours 30', 'seconds' => 9000],
|
||||
[ 'label' => '3 hours', 'seconds' => 10800],
|
||||
[ 'label' => '3 hours 30', 'seconds' => 12600],
|
||||
[ 'label' => '4 hours', 'seconds' => 14400],
|
||||
[ 'label' => '4 hours 30', 'seconds' => 16200],
|
||||
[ 'label' => '5 hours', 'seconds' => 18000],
|
||||
[ 'label' => '5 hours 30', 'seconds' => 19800],
|
||||
[ 'label' => '6 hours', 'seconds' => 21600],
|
||||
[ 'label' => '6 hours 30', 'seconds' => 23400],
|
||||
[ 'label' => '7 hours', 'seconds' => 25200],
|
||||
[ 'label' => '7 hours 30', 'seconds' => 27000],
|
||||
[ 'label' => '8 hours', 'seconds' => 28800],
|
||||
[ 'label' => '8 hours 30', 'seconds' => 30600],
|
||||
[ 'label' => '9 hours', 'seconds' => 32400],
|
||||
[ 'label' => '9 hours 30', 'seconds' => 34200],
|
||||
[ 'label' => '10 hours', 'seconds' => 36000],
|
||||
[ 'label' => '1/2 day', 'seconds' => 14040],
|
||||
[ 'label' => '1 day', 'seconds' => 28080],
|
||||
[ 'label' => '1 1/2 days', 'seconds' => 42120],
|
||||
[ 'label' => '2 days', 'seconds' => 56160],
|
||||
[ 'label' => '2 1/2 days', 'seconds' => 70200],
|
||||
[ 'label' => '3 days', 'seconds' => 84240],
|
||||
[ 'label' => '3 1/2 days', 'seconds' => 98280],
|
||||
[ 'label' => '4 days', 'seconds' => 112320],
|
||||
[ 'label' => '4 1/2 days', 'seconds' => 126360],
|
||||
[ 'label' => '5 days', 'seconds' => 140400],
|
||||
[ 'label' => '5 1/2 days', 'seconds' => 154440],
|
||||
[ 'label' => '6 days', 'seconds' => 168480],
|
||||
[ 'label' => '6 1/2 days', 'seconds' => 182520],
|
||||
[ 'label' => '7 days', 'seconds' => 196560],
|
||||
[ 'label' => '7 1/2 days', 'seconds' => 210600],
|
||||
[ 'label' => '8 days', 'seconds' => 224640],
|
||||
[ 'label' => '8 1/2 days', 'seconds' => 238680],
|
||||
[ 'label' => '9 days', 'seconds' => 252720],
|
||||
[ 'label' => '9 1/2 days', 'seconds' => 266760],
|
||||
[ 'label' => '10 days', 'seconds' => 280800],
|
||||
[ 'label' => '10 1/2days', 'seconds' => 294840],
|
||||
[ 'label' => '11 days', 'seconds' => 308880],
|
||||
[ 'label' => '11 1/2 days', 'seconds' => 322920],
|
||||
[ 'label' => '12 days', 'seconds' => 336960],
|
||||
[ 'label' => '12 1/2 days', 'seconds' => 351000],
|
||||
[ 'label' => '13 days', 'seconds' => 365040],
|
||||
[ 'label' => '13 1/2 days', 'seconds' => 379080],
|
||||
[ 'label' => '14 days', 'seconds' => 393120],
|
||||
[ 'label' => '14 1/2 days', 'seconds' => 407160],
|
||||
[ 'label' => '15 days', 'seconds' => 421200],
|
||||
[ 'label' => '15 1/2 days', 'seconds' => 435240],
|
||||
[ 'label' => '16 days', 'seconds' => 449280],
|
||||
[ 'label' => '16 1/2 days', 'seconds' => 463320],
|
||||
[ 'label' => '17 days', 'seconds' => 477360],
|
||||
[ 'label' => '17 1/2 days', 'seconds' => 491400],
|
||||
[ 'label' => '18 days', 'seconds' => 505440],
|
||||
[ 'label' => '18 1/2 days', 'seconds' => 519480],
|
||||
[ 'label' => '19 days', 'seconds' => 533520],
|
||||
[ 'label' => '19 1/2 days', 'seconds' => 547560],
|
||||
[ 'label' => '20 days', 'seconds' => 561600],
|
||||
[ 'label' => '20 1/2 days', 'seconds' => 575640],
|
||||
[ 'label' => '21 days', 'seconds' => 580680],
|
||||
[ 'label' => '21 1/2 days', 'seconds' => 603720],
|
||||
[ 'label' => '22 days', 'seconds' => 617760],
|
||||
[ 'label' => '22 1/2 days', 'seconds' => 631800],
|
||||
[ 'label' => '23 days', 'seconds' => 645840],
|
||||
[ 'label' => '23 1/2 days', 'seconds' => 659880],
|
||||
[ 'label' => '24 days', 'seconds' => 673920],
|
||||
[ 'label' => '24 1/2 days', 'seconds' => 687960],
|
||||
[ 'label' => '25 days', 'seconds' => 702000],
|
||||
[ 'label' => '25 1/2 days', 'seconds' => 716040],
|
||||
[ 'label' => '26 days', 'seconds' => 730080],
|
||||
[ 'label' => '26 1/2 days', 'seconds' => 744120],
|
||||
[ 'label' => '27 days', 'seconds' => 758160],
|
||||
[ 'label' => '27 1/2 days', 'seconds' => 772200],
|
||||
[ 'label' => '28 days', 'seconds' => 786240],
|
||||
[ 'label' => '28 1/2 days', 'seconds' => 800280],
|
||||
[ 'label' => '29 days', 'seconds' => 814320],
|
||||
[ 'label' => '29 1/2 days', 'seconds' => 828360],
|
||||
[ 'label' => '30 days', 'seconds' => 842400],
|
||||
]
|
||||
)
|
||||
->info('The intervals of time to show in activity form')
|
||||
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('seconds')
|
||||
->info("The number of seconds of this duration. Must be an integer.")
|
||||
->cannotBeEmpty()
|
||||
->validate()
|
||||
->ifTrue(function($data) {
|
||||
return !is_int($data);
|
||||
})->thenInvalid("The value %s is not a valid integer")
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('label')
|
||||
->cannotBeEmpty()
|
||||
->info("The label to show into fields")
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ namespace Chill\AsideActivityBundle\Entity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
@ -27,10 +29,33 @@ class AsideActivityCategory
|
||||
private array $title;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private bool $isActive = true;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
* @ORM\Column(type="float", options={"default": 0.00})
|
||||
*/
|
||||
private float $ordering = 0.00;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AsideActivityCategory::class, inversedBy="children")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -59,4 +84,85 @@ class AsideActivityCategory
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent(): ?self
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Assert\Callback()
|
||||
*/
|
||||
public function preventRecursiveParent(ExecutionContextInterface $context, $payload)
|
||||
{
|
||||
if (!$this->hasParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getParent() === $this) {
|
||||
// replace parent with old parent. This prevent recursive loop
|
||||
// when displaying form
|
||||
$this->parent = $this->oldParent;
|
||||
$context->buildViolation('You must not add twice the same category in the parent tree (previous result returned)')
|
||||
->atPath('parent')
|
||||
->addViolation()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
public function setParent(?self $parent): self
|
||||
{
|
||||
// cache the old result for changing it during validaiton
|
||||
$this->oldParent = $this->parent;
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|self[]
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
public function addChild(self $child): self
|
||||
{
|
||||
if (!$this->children->contains($child)) {
|
||||
$this->children[] = $child;
|
||||
$child->setParent($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeChild(self $child): self
|
||||
{
|
||||
if ($this->children->removeElement($child)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($child->getParent() === $this) {
|
||||
$child->setParent(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrdering(): float
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
public function setOrdering(float $ordering): AsideActivityCategory
|
||||
{
|
||||
$this->ordering = $ordering;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -3,21 +3,43 @@
|
||||
namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class AsideActivityCategoryType extends AbstractType
|
||||
{
|
||||
|
||||
protected $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, CategoryRender $categoryRender)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('title', TranslatableStringFormType::class,
|
||||
[
|
||||
'label' => 'Nom',
|
||||
])
|
||||
->add('isActive', ChoiceType::class,
|
||||
->add('parent', EntityType::class, [
|
||||
'class' => AsideActivityCategory::class,
|
||||
'required' => false,
|
||||
'label' => 'Parent',
|
||||
'choice_label' => function (AsideActivityCategory $category){
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($category, $options);
|
||||
}
|
||||
])
|
||||
->add('ordering', NumberType::class)
|
||||
->add('isActive', ChoiceType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'Yes' => true,
|
||||
|
@ -4,11 +4,13 @@ namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\ChillTextareaType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
@ -16,26 +18,27 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTra
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class AsideActivityFormType extends AbstractType
|
||||
{
|
||||
protected array $timeChoices;
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private TokenStorageInterface $storage;
|
||||
private CategoryRender $categoryRender;
|
||||
|
||||
public function __construct (
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ParameterBagInterface $parameterBag,
|
||||
TokenStorageInterface $storage
|
||||
TokenStorageInterface $storage,
|
||||
CategoryRender $categoryRender
|
||||
){
|
||||
$this->timeChoices = $parameterBag->get('chill_activity.form.time_duration');
|
||||
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->storage = $storage;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@ -70,11 +73,6 @@ final class AsideActivityFormType extends AbstractType
|
||||
[
|
||||
'label' => 'date',
|
||||
'data' => new \DateTime(),
|
||||
//SETTING RANGE ONLY POSSIBLE WITH WIDGET 'CHOICE' AND NOT 'SINGLE_TEXT'?
|
||||
// 'widget' => 'choice',
|
||||
// 'years' => range(2020, date('Y')),
|
||||
// 'months' => range(1, date('m')),
|
||||
// 'days' => range(1, date('d')),
|
||||
'required' => true
|
||||
])
|
||||
->add('type', EntityType::class,
|
||||
@ -83,9 +81,17 @@ final class AsideActivityFormType extends AbstractType
|
||||
'required' => true,
|
||||
'class' => AsideActivityCategory::class,
|
||||
'placeholder' => 'Choose the activity category',
|
||||
// 'choice_label' => 'title[""]'
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('ac');
|
||||
$qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
|
||||
->addOrderBy('ac.ordering', 'ASC')
|
||||
;
|
||||
|
||||
return $qb;
|
||||
},
|
||||
'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
|
||||
return $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($asideActivityCategory, $options);
|
||||
},
|
||||
])
|
||||
->add('duration', ChoiceType::class, $durationTimeOptions)
|
||||
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['admin_index', 'admin_section', 'admin_aside_activity'];
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
// all the entries below must have ROLE_ADMIN permissions
|
||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($menuId, ['admin_index', 'admin_section'])) {
|
||||
$menu->addChild('Aside activities', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 900,
|
||||
'explain' => "Configure aside activities categories"
|
||||
]);
|
||||
} else {
|
||||
$menu
|
||||
->addChild('Aside activity categories', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => '50'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
@ -14,10 +16,12 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
protected TranslatorInterface $translator;
|
||||
public AuthorizationCheckerInterface $authorizationChecker;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
public function __construct(TranslatorInterface $translator, AuthorizationCheckerInterface $authorizationChecker)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,13 +31,26 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
*/
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
$menu->addChild($this->translator->trans('Create an aside activity'), [
|
||||
'route' => 'chill_crud_aside_activity_new'
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild($this->translator->trans('Create an aside activity'), [
|
||||
'route' => 'chill_crud_aside_activity_new'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 11,
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
$menu->addChild($this->translator->trans('Phonecall'), [
|
||||
'route' => 'chill_crud_aside_activity_new',
|
||||
'routeParameters' => [
|
||||
'type' => 1,
|
||||
'duration' => 900,
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 11,
|
||||
'icons' => [ 'plus' ]
|
||||
'order' => 12,
|
||||
'icons' => ['plus']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs Libres Cooperative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Chill\TaskBundle\Templating\UI\CountNotificationTask;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class UserMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CountNotificationTask
|
||||
*/
|
||||
public $counter;
|
||||
|
||||
/*
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
public $tokenStorage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
public $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
public $authorizationChecker;
|
||||
|
||||
public function __construct(
|
||||
CountNotificationTask $counter,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
TranslatorInterface $translator,
|
||||
AuthorizationCheckerInterface $authorizationChecker
|
||||
) {
|
||||
$this->counter = $counter;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild("My aside activities", [
|
||||
'route' => 'chill_crud_aside_activity_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 10,
|
||||
'icon' => 'tasks'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'user' ];
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,12 @@
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_aside_activity', {
|
||||
'layout': '@ChillAsideActivity/Admin/menu_asideactivity.html.twig',
|
||||
}) }}
|
||||
{{ chill_menu('admin_aside_activity') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}
|
||||
<!-- block personcontent empty -->
|
||||
<h1>{{ 'Aside activity configuration' |trans }}</h1>
|
||||
<h1>{{ 'Aside activity configuration'|trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -1,4 +0,0 @@
|
||||
{% extends "@ChillMain/Menu/verticalMenu.html.twig" %}
|
||||
{% block v_menu_title %}
|
||||
{{ 'Aside activity configuration menu'|trans }}
|
||||
{% endblock %}
|
@ -0,0 +1,12 @@
|
||||
{% set reversed_parents = parents|reverse %}
|
||||
<span
|
||||
class="chill-entity entity-aside_activity-category">
|
||||
{%- for p in reversed_parents %}
|
||||
<span class="parent-{{ loop.revindex0 }}">
|
||||
{{ p.title|localize_translatable_string }}{{ options['default.separator'] }}
|
||||
</span>
|
||||
{%- endfor -%}
|
||||
<span class="child">
|
||||
{{ asideActivityCategory.title|localize_translatable_string }}
|
||||
</span>
|
||||
</span>
|
@ -1,8 +1,91 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ ('crud.' ~ crud_name ~ '.index.title')|trans({'%crud_name%': crud_name}) }}{% endblock %}
|
||||
{% block title %}
|
||||
{{ 'Aside activity list'|trans }}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillAsideActivity/AsideActivity/_index.html.twig' %}
|
||||
{% endembed %}
|
||||
{% endblock content %}
|
||||
<div class="col-md-10 asideactivity-list">
|
||||
<h2>{{ 'My aside activities'|trans }}</h2>
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There aren't any aside activities."|trans }}
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table">
|
||||
|
||||
{% for entity in entities %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row wrap-header">
|
||||
|
||||
<div class="item-col">
|
||||
<h3>
|
||||
{{ entity.type|chill_entity_render_box }}
|
||||
</h3>
|
||||
<div>
|
||||
{% if entity.date %}
|
||||
<span>{{ entity.date|format_date('long') }}</span>
|
||||
{% endif %}
|
||||
{% if entity.date %}
|
||||
<span class="duration">
|
||||
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ entity.duration|date('H:i') }}
|
||||
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<div class="box">
|
||||
<ul class="list-content fa-ul">
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
||||
<b>{{ entity.createdBy|chill_entity_render_box }}</b>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
||||
<b>{{ entity.agent|chill_entity_render_box }}</b>
|
||||
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_view', { 'id': entity.id } ) }}" class="btn btn-show btn-mini"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_edit', { 'id': entity.id }) }}" class="btn btn-update btn-mini "></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_delete', { 'id': entity.id } ) }}" class="btn btn-delete btn-mini"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_new') }}" class="btn btn-create">
|
||||
{{ 'Create'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -1,97 +0,0 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ 'Aside activity list' |trans }}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 col-xxl asideactivity-list">
|
||||
<h2>{{ 'My aside activities' |trans }}</h2>
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There aren't any aside activities."|trans }}
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div
|
||||
class="flex-table my-4 list-records">
|
||||
{# Sort activities according to date in descending order #}
|
||||
{% for entity in entities %}
|
||||
{% set t = entity.type %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
<h3>
|
||||
<b>{{ entity.type.title | localize_translatable_string }}</b>
|
||||
</h3>
|
||||
|
||||
{% if entity.date %}
|
||||
<p>{{ entity.date|format_date('long') }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ entity.duration|date('H:i') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if entity.createdBy %}
|
||||
<li>
|
||||
<b>{{ 'Created by: '|trans }}{{ entity.createdBy.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# {%
|
||||
if entity.note is not empty
|
||||
or entity.createdBy|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
{% if entity.note is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ entity.note|chill_markdown_to_html }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endif %} #}
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_edit', { 'id': entity.id }) }}" class="btn btn-update btn-mini "></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_delete', { 'id': entity.id } ) }}" class="btn btn-delete btn-mini"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_new') }}" class="btn btn-create">
|
||||
{{ 'Create' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -3,13 +3,50 @@
|
||||
{% set activeRouteKey = '' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_view_title.html.twig') %}
|
||||
{% include('@ChillMain/CRUD/_view_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillMain/CRUD/_view_content.html.twig' %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_view')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
{% embed '@ChillMain/CRUD/_view_content.html.twig' %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_view')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% block crud_content_view_details %}
|
||||
<dl class="chill_view_data">
|
||||
|
||||
<dt class="inline">{{ 'Type'|trans }}</dt>
|
||||
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
||||
<dd>{{ entity.createdBy }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
||||
<dd>{{ entity.agent }}</dd>
|
||||
|
||||
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
|
||||
|
||||
<dt class="inline">{{ 'Date'|trans }}</dt>
|
||||
<dd>{{ entity.date|format_date('long') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Duration'|trans }}</dt>
|
||||
<dd>{{ entity.duration|date('H:i') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Remark'|trans }}</dt>
|
||||
{%- if entity.note is empty -%}
|
||||
<dd>
|
||||
<span class="chill-no-data-statement">{{ 'No comments'|trans }}</span>
|
||||
</dd>
|
||||
{%- else -%}
|
||||
<dd>
|
||||
<section class="chill-entity entity-comment-embeddable">
|
||||
<blockquote class="chill-user-quote">
|
||||
<p>{{ entity.note }}</p>
|
||||
</blockquote>
|
||||
</section>
|
||||
</dd>
|
||||
{%- endif -%}
|
||||
</dl>
|
||||
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
|
@ -1,11 +1,12 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'ActivityType list'|trans }}</h1>
|
||||
<h1>{{ 'Aside Activity Type list'|trans }}</h1>
|
||||
|
||||
<table class="records_list table table-bordered border-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Ordering'|trans }}</th>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
@ -14,7 +15,8 @@
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.title|localize_translatable_string }}</td>
|
||||
<td>{{ entity.ordering }}</td>
|
||||
<td>{{ entity|chill_entity_render_box }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.isActive -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Templating\Entity;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class CategoryRender implements ChillEntityRenderInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private EngineInterface $engine;
|
||||
|
||||
public const SEPERATOR_KEY = 'default.separator';
|
||||
public const DEFAULT_ARGS = [
|
||||
self::SEPERATOR_KEY => ' > '
|
||||
];
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, EngineInterface $engine)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderString($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
|
||||
while ($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $asideActivityCategory->getParent();
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
}
|
||||
|
||||
$titles = array_reverse($titles);
|
||||
|
||||
return implode($options[self::SEPERATOR_KEY], $titles);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function supports($asideActivityCategory, array $options): bool
|
||||
{
|
||||
return $asideActivityCategory instanceof AsideActivityCategory;
|
||||
}
|
||||
|
||||
public function buildParents(AsideActivityCategory $asideActivityCategory)
|
||||
{
|
||||
$parents = [];
|
||||
|
||||
while($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $parents[] = $asideActivityCategory->getParent();
|
||||
}
|
||||
|
||||
return $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderBox($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
$parents = $this->buildParents($asideActivityCategory);
|
||||
|
||||
return $this->engine->render('@ChillAsideActivity/Entity/asideActivityCategory.html.twig',
|
||||
[
|
||||
'asideActivityCategory' => $asideActivityCategory,
|
||||
'parents' => $parents,
|
||||
'options' => $options
|
||||
]);
|
||||
}
|
||||
}
|
@ -1,5 +1,22 @@
|
||||
services:
|
||||
Chill\AsideActivityBundle\DataFixtures\:
|
||||
resource: './../DataFixtures'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
Chill\AsideActivityBundle\DataFixtures\:
|
||||
resource: "./../DataFixtures"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Templating\Entity\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: "../Templating/Entity"
|
||||
tags:
|
||||
- "chill.render_entity"
|
||||
|
||||
Chill\AsideActivityBundle\Repository\:
|
||||
resource: "../Repository"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Controller\:
|
||||
resource: "../Controller"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@ -1,5 +1,5 @@
|
||||
services:
|
||||
Chill\AsideActivityBundle\Menu\:
|
||||
resource: './../../Menu'
|
||||
resource: "./../../Menu"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@ -7,14 +7,11 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210706124644 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
return 'Aside activity category entity created';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@ -7,14 +7,11 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210804082249 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
return 'Aside activity entity created';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
@ -59,12 +56,12 @@ final class Version20210804082249 extends AbstractMigration
|
||||
$this->addSql('CREATE INDEX idx_e9fa219165ff1aec ON asideactivity (updatedby_id)');
|
||||
$this->addSql('CREATE INDEX idx_e9fa21913414710b ON asideactivity (agent_id)');
|
||||
$this->addSql('COMMENT ON COLUMN asideactivity.updatedat IS \'(DC2Type:datetime_immutable)\'');
|
||||
$this->addSql('CREATE TABLE chill_main_address_legacy (id INT DEFAULT NULL, postcode_id INT DEFAULT NULL, street VARCHAR(255) DEFAULT NULL, streetnumber VARCHAR(255) DEFAULT NULL, validfrom DATE DEFAULT NULL, isnoaddress BOOLEAN DEFAULT NULL, customs JSONB DEFAULT NULL, floor VARCHAR(16) DEFAULT NULL, corridor VARCHAR(16) DEFAULT NULL, steps VARCHAR(16) DEFAULT NULL, buildingname VARCHAR(255) DEFAULT NULL, flat VARCHAR(16) DEFAULT NULL, distribution VARCHAR(255) DEFAULT NULL, extra VARCHAR(255) DEFAULT NULL, validto DATE DEFAULT NULL, point VARCHAR(255) DEFAULT NULL, linkedtothirdparty_id INT DEFAULT NULL)');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa2191c54c8c93 FOREIGN KEY (type_id) REFERENCES asideactivitytype (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa21913174800f FOREIGN KEY (createdby_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa219165ff1aec FOREIGN KEY (updatedby_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa21913414710b FOREIGN KEY (agent_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('DROP TABLE chill_asideactivity.AsideActivity');
|
||||
$this->addSql('DROP TABLE chill_asideactivity.AsideActivityCategory');
|
||||
$this->addSql('DROP SCHEMA chill_asideactivity');
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,11 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210806140343 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
return 'Duration changed to type integer';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@ -7,14 +7,11 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210806140710 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
return 'Duration changed back to timestamp';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@ -7,14 +7,11 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210810084456 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
return 'createdat, updatedat and date given a type timestamp';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\AsideActivity;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20210922182907 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Parent and children added to aside activity category entity';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD parent_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD CONSTRAINT FK_7BF90DBE727ACA70 FOREIGN KEY (parent_id) REFERENCES chill_asideactivity.AsideActivityCategory (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_7BF90DBE727ACA70 ON chill_asideactivity.asideactivitycategory (parent_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.AsideActivityCategory DROP parent');
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\AsideActivity;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* allow to add an ordering to aside activity categories
|
||||
*/
|
||||
final class Version20211004134012 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'allow to add an ordering to aside activity categories';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD ordering DOUBLE PRECISION NOT NULL DEFAULT 0.00');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory DROP ordering');
|
||||
}
|
||||
}
|
@ -14,11 +14,8 @@ present: présent
|
||||
not present: absent
|
||||
Delete: Supprimer
|
||||
Update: Mettre à jour
|
||||
Update activity: Modifier l'activité
|
||||
Aside activity data: Données de l'activité annexe
|
||||
No reason associated: Aucun sujet
|
||||
There aren't any aside activities.: Aucune activité annexe enregistrée.
|
||||
type_name: type de l'activité
|
||||
Type: Type
|
||||
Invisible: Invisible
|
||||
Optional: Optionnel
|
||||
@ -43,14 +40,8 @@ crud:
|
||||
title_edit: Edition d'une catégorie de type d'activité
|
||||
|
||||
#forms
|
||||
Activity creation: Nouvelle activité annexe
|
||||
Create a new aside activity type: Nouvelle catégorie d'activité annexe
|
||||
Create: Créer
|
||||
Create a new aside activity type: Nouvelle categorie d'activité annexe
|
||||
Back to the list: Retour à la liste
|
||||
Save activity: Sauver l'activité
|
||||
Reset form: Remise à zéro du formulaire
|
||||
Choose the agent for whom this activity is created: Choisissez l'utilisateur pour qui l'activité est créée.
|
||||
Choose the activity category: Choisissez le type d'activité
|
||||
Choose the duration: Choisir la durée
|
||||
Choose a category: Choisir une catégorie
|
||||
Is active: Actif
|
||||
@ -58,12 +49,106 @@ Agent: Utilisateur
|
||||
date: Date
|
||||
Duration: Durée
|
||||
Note: Note
|
||||
Choose the agent for whom this activity is created: Choisissez l'agent pour qui l'activité est créée
|
||||
Choose the activity category: Choisir la catégorie
|
||||
|
||||
#Duration
|
||||
minutes: minutes
|
||||
hour: heure
|
||||
hours: heures
|
||||
day: jour
|
||||
days: jours
|
||||
5 minutes: 5 minutes
|
||||
10 minutes: 10 minutes
|
||||
15 minutes: 15 minutes
|
||||
20 minutes: 20 minutes
|
||||
25 minutes: 25 minutes
|
||||
30 minutes: 30 minutes
|
||||
45 minutes: 45 minutes
|
||||
1 hour: 1 heure
|
||||
1 hour 15: 1 heure 15
|
||||
1 hour 30: 1 heure 30
|
||||
1 hour 45: 1 heure 45
|
||||
2 hours: 2 heures
|
||||
2 hours 30: 2 heure 30
|
||||
3 hours: 3 heures
|
||||
3 hours 30: 3 heure 30
|
||||
4 hours: 4 heures
|
||||
4 hours 30: 4 heure 30
|
||||
5 hours: 5 heures
|
||||
5 hours 30: 5 heure 30
|
||||
6 hours: 6 heures
|
||||
6 hours 30: 6 heure 30
|
||||
7 hours: 7 heures
|
||||
7 hours 30: 7 heure 30
|
||||
8 hours: 8 heures
|
||||
8 hours 30: 8 heure 30
|
||||
9 hours: 9 heures
|
||||
9 hours 30: 9 heure 30
|
||||
10 hours: 10 heures
|
||||
1/2 day: 1/2 jour
|
||||
1 day: 1 jour
|
||||
1 1/2 days: 1 1/2 jours
|
||||
2 days: 2 jours
|
||||
2 1/2 days: 2 1/2 jours
|
||||
3 days: 3 jours
|
||||
3 1/2 days: 3 1/2 jours
|
||||
4 days: 4 jours
|
||||
4 1/2 days: 4 1/2 jours
|
||||
5 days: 5 jours
|
||||
5 1/2 days: 5 1/2 jours
|
||||
6 days: 6 jours
|
||||
6 1/2 days: 6 1/2 jours
|
||||
7 days: 7 jours
|
||||
7 1/2 days: 7 1/2 jours
|
||||
8 days: 8 jours
|
||||
8 1/2 days: 8 1/2 jours
|
||||
9 days: 9 jours
|
||||
9 1/2 days: 9 1/2 jours
|
||||
10 days: 10 jours
|
||||
10 1/2 days: 10 1/2 jours
|
||||
11 days: 11 jours
|
||||
11 1/2 days: 11 1/2 jours
|
||||
12 days: 12 jours
|
||||
12 1/2 days: 12 1/2 jours
|
||||
13 days: 13 jours
|
||||
13 1/2 days: 13 1/2 jours
|
||||
14 days: 14 jours
|
||||
14 1/2 days: 14 1/2 jours
|
||||
15 days: 15 jours
|
||||
15 1/2 days: 15 1/2 jours
|
||||
16 days: 16 jours
|
||||
16 1/2 days: 16 1/2 jours
|
||||
17 days: 17 jours
|
||||
17 1/2 days: 17 1/2 jours
|
||||
18 days: 18 jours
|
||||
18 1/2 days: 18 1/2 jours
|
||||
19 days: 19 jours
|
||||
19 1/2 days: 19 1/2 jours
|
||||
20 days: 20 jours
|
||||
20 1/2 days: 20 1/2 jours
|
||||
21 days: 21 jours
|
||||
21 1/2 days: 21 1/2 jours
|
||||
22 days: 22 jours
|
||||
22 1/2 days: 22 1/2 jours
|
||||
23 days: 23 jours
|
||||
23 1/2 days: 23 1/2 jours
|
||||
24 days: 24 jours
|
||||
24 1/2 days: 24 1/2 jours
|
||||
25 days: 25 jours
|
||||
25 1/2 days: 25 1/2 jours
|
||||
26 days: 26 jours
|
||||
26 1/2 days: 26 1/2 jours
|
||||
27 days: 27 jours
|
||||
27 1/2 days: 27 1/2 jours
|
||||
28 days: 28 jours
|
||||
28 1/2 days: 28 1/2 jours
|
||||
29 days: 29 jours
|
||||
29 1/2 days: 29 1/2 jours
|
||||
30 days: 30 jours
|
||||
|
||||
#list
|
||||
My aside activities: Mes activités annexes
|
||||
Date: Date
|
||||
Created by: Créée par
|
||||
|
||||
#Aside activity delete
|
||||
Delete aside activity: Supprimer une activité annexe
|
||||
Are you sure you want to remove the aside activity concerning "%name%" ?: Êtes-vous sûr de vouloir supprimer une activité annexe qui concerne "%name%" ?
|
||||
@ -73,3 +158,4 @@ The activity has been successfully removed.: L'activité a été supprimée.
|
||||
Create an aside activity: "Créer une activité annexe"
|
||||
Aside activity configuration menu: "Menu de configuration des activités annexes"
|
||||
Aside activity configuration: "Configuration des activités annexes"
|
||||
Phonecall: "Appel téléphonique"
|
||||
|
@ -0,0 +1 @@
|
||||
You must not add twice the same category in the parent tree (previous result returned): Il est interdit d'indiquer la même entité dans l'arbre des parents. Le résultat précédent a été rétabli
|
@ -20,6 +20,8 @@
|
||||
|
||||
namespace Chill\MainBundle\CRUD\Controller;
|
||||
|
||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
|
||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -209,22 +211,24 @@ class CRUDController extends AbstractController
|
||||
* This method:
|
||||
*
|
||||
* 1. Launch `onPreIndex`
|
||||
* x. check acl. If it does return a response instance, return it
|
||||
* x. launch `onPostCheckACL`. If it does return a response instance, return it
|
||||
* 1. count the items, using `countEntities`
|
||||
* 2. build a paginator element from the the number of entities ;
|
||||
* 3. Launch `onPreIndexQuery`. If it does return a response instance, return it
|
||||
* 3. build a query, using `queryEntities`
|
||||
* x. fetch the results, using `getQueryResult`
|
||||
* x. Launch `onPostIndexFetchQuery`. If it does return a response instance, return it
|
||||
* 4. create default parameters:
|
||||
* 2. check acl. If it does return a response instance, return it
|
||||
* 3. launch `onPostCheckACL`. If it does return a response instance, return it
|
||||
* 4. count the items, using `countEntities`
|
||||
* 5. build a paginator element from the the number of entities ;
|
||||
* 6. Launch `onPreIndexQuery`. If it does return a response instance, return it
|
||||
* 7. fetch the results, using `getQueryResult`
|
||||
*
|
||||
* Internally, this build a query, using `queryEntities`
|
||||
*
|
||||
* 8. Launch `onPostIndexFetchQuery`. If it does return a response instance, return it
|
||||
* 9. create default parameters:
|
||||
*
|
||||
* The default parameters are:
|
||||
*
|
||||
* * entities: the list en entities ;
|
||||
* * crud_name: the name of the crud ;
|
||||
* * paginator: a paginator element ;
|
||||
* 5. Launch rendering, the parameter is fetch using `getTemplateFor`
|
||||
* 10. Launch rendering, the parameter is fetch using `getTemplateFor`
|
||||
* The parameters may be personnalized using `generateTemplateParameter`.
|
||||
*
|
||||
* @param string $action
|
||||
@ -249,7 +253,8 @@ class CRUDController extends AbstractController
|
||||
return $response;
|
||||
}
|
||||
|
||||
$totalItems = $this->countEntities($action, $request);
|
||||
$filterOrder = $this->buildFilterOrderHelper($action, $request);
|
||||
$totalItems = $this->countEntities($action, $request, $filterOrder);
|
||||
$paginator = $this->getPaginatorFactory()->create($totalItems);
|
||||
|
||||
$response = $this->onPreIndexBuildQuery($action, $request, $totalItems,
|
||||
@ -259,16 +264,7 @@ class CRUDController extends AbstractController
|
||||
return $response;
|
||||
}
|
||||
|
||||
$query = $this->queryEntities($action, $request, $paginator);
|
||||
|
||||
$response = $this->onPostIndexBuildQuery($action, $request, $totalItems,
|
||||
$paginator, $query);
|
||||
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$entities = $this->getQueryResult($action, $request, $totalItems, $paginator, $query);
|
||||
$entities = $this->getQueryResult($action, $request, $totalItems, $paginator, $filterOrder);
|
||||
|
||||
$response = $this->onPostIndexFetchQuery($action, $request, $totalItems,
|
||||
$paginator, $entities);
|
||||
@ -280,7 +276,8 @@ class CRUDController extends AbstractController
|
||||
$defaultTemplateParameters = [
|
||||
'entities' => $entities,
|
||||
'crud_name' => $this->getCrudName(),
|
||||
'paginator' => $paginator
|
||||
'paginator' => $paginator,
|
||||
'filter_order' => $filterOrder
|
||||
];
|
||||
|
||||
return $this->render(
|
||||
@ -289,6 +286,11 @@ class CRUDController extends AbstractController
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildFilterOrderHelper(string $action, Request $request): ?FilterOrderHelper
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
@ -361,9 +363,9 @@ class CRUDController extends AbstractController
|
||||
* @param PaginatorInterface $paginator
|
||||
* @return type
|
||||
*/
|
||||
protected function queryEntities(string $action, Request $request, PaginatorInterface $paginator)
|
||||
protected function queryEntities(string $action, Request $request, PaginatorInterface $paginator, ?FilterOrderHelper $filterOrder = null)
|
||||
{
|
||||
$query = $this->buildQueryEntities($action, $request)
|
||||
$query = $this->buildQueryEntities($action, $request, $filterOrder)
|
||||
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
|
||||
->setMaxResults($paginator->getItemsPerPage());
|
||||
|
||||
@ -393,11 +395,13 @@ class CRUDController extends AbstractController
|
||||
* @param Request $request
|
||||
* @param int $totalItems
|
||||
* @param PaginatorInterface $paginator
|
||||
* @param mixed $query
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getQueryResult(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, $query)
|
||||
protected function getQueryResult(string $action, Request $request, int $totalItems, PaginatorInterface $paginator,
|
||||
?FilterOrderHelper $filterOrder = null)
|
||||
{
|
||||
$query = $this->queryEntities($action, $request, $paginator, $filterOrder);
|
||||
|
||||
return $query->getQuery()->getResult();
|
||||
}
|
||||
|
||||
@ -408,9 +412,9 @@ class CRUDController extends AbstractController
|
||||
* @param Request $request
|
||||
* @return int
|
||||
*/
|
||||
protected function countEntities(string $action, Request $request): int
|
||||
protected function countEntities(string $action, Request $request, ?FilterOrderHelper $filterOrder = null): int
|
||||
{
|
||||
return $this->buildQueryEntities($action, $request)
|
||||
return $this->buildQueryEntities($action, $request, $filterOrder)
|
||||
->select('COUNT(e)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult()
|
||||
@ -1183,6 +1187,11 @@ class CRUDController extends AbstractController
|
||||
return $this->get(Resolver::class);
|
||||
}
|
||||
|
||||
protected function getFilterOrderHelperFactory(): FilterOrderHelperFactoryInterface
|
||||
{
|
||||
return $this->get(FilterOrderHelperFactoryInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@ -1197,6 +1206,7 @@ class CRUDController extends AbstractController
|
||||
EventDispatcherInterface::class => EventDispatcherInterface::class,
|
||||
Resolver::class => Resolver::class,
|
||||
SerializerInterface::class => SerializerInterface::class,
|
||||
FilterOrderHelperFactoryInterface::class => FilterOrderHelperFactoryInterface::class,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@ -69,6 +71,9 @@ class LoadPostalCodesCommand extends Command
|
||||
. "using the postal code and name. \n"
|
||||
. "The CSV file must have the following columns: "
|
||||
. "postal code, label, country code."
|
||||
. "Optionally, the csv file can have the following "
|
||||
. "columns after the country code: reference code, latitude, longitude, source. "
|
||||
. "The latitude and longitude columns are supposed to be in WGS84 and expressed in decimal degrees. "
|
||||
. "The CSV file should not have any header row.")
|
||||
->addArgument('csv_file', InputArgument::REQUIRED, "the path to "
|
||||
. "the csv file. See the help for specifications.")
|
||||
@ -163,7 +168,7 @@ class LoadPostalCodesCommand extends Command
|
||||
}
|
||||
$em = $this->entityManager;
|
||||
$country = $em
|
||||
->getRepository('ChillMainBundle:Country')
|
||||
->getRepository(Country::class)
|
||||
->findOneBy(array('countryCode' => $row[2]));
|
||||
|
||||
if ($country === NULL) {
|
||||
@ -173,7 +178,7 @@ class LoadPostalCodesCommand extends Command
|
||||
|
||||
// try to find an existing postal code
|
||||
$existingPC = $em
|
||||
->getRepository('ChillMainBundle:PostalCode')
|
||||
->getRepository(PostalCode::class)
|
||||
->findBy(array('code' => $row[0], 'name' => $row[1]));
|
||||
|
||||
if (count($existingPC) > 0) {
|
||||
@ -187,6 +192,18 @@ class LoadPostalCodesCommand extends Command
|
||||
->setCountry($country)
|
||||
;
|
||||
|
||||
if (NULL != $row[3]){
|
||||
$postalCode->setRefPostalCodeId($row[3]);
|
||||
}
|
||||
|
||||
if (NULL != $row[4] & NULL != $row[5]){
|
||||
$postalCode->setCenter(Point::fromLonLat((float) $row[5], (float) $row[4]));
|
||||
}
|
||||
|
||||
if (NULL != $row[6]){
|
||||
$postalCode->setPostalCodeSource($row[6]);
|
||||
}
|
||||
|
||||
$errors = $this->validator->validate($postalCode);
|
||||
|
||||
if ($errors->count() == 0) {
|
||||
|
@ -1,22 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ThirdPartyBundle\DataFixtures\ORM;
|
||||
namespace Chill\MainBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdPartyCivility;
|
||||
use Chill\MainBundle\Entity\Civility;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Class LoadThirdPartyCivility
|
||||
* @package Chill\ThirdPartyBundle\DataFixtures\ORM
|
||||
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
|
||||
*/
|
||||
class LoadThirdPartyCivility extends Fixture implements FixtureGroupInterface
|
||||
class LoadCivility extends Fixture implements FixtureGroupInterface
|
||||
{
|
||||
public static function getGroups(): array
|
||||
{
|
||||
return ['thirdparty_civilities'];
|
||||
return ['civilities'];
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager): void
|
||||
@ -34,8 +29,7 @@ class LoadThirdPartyCivility extends Fixture implements FixtureGroupInterface
|
||||
];
|
||||
|
||||
foreach ( $civilities as $val) {
|
||||
print "Creating thirdparty civility : " . $val['name']['fr'] . "\n";
|
||||
$civility = (new ThirdPartyCivility())
|
||||
$civility = (new Civility())
|
||||
->setName($val['name'])
|
||||
->setActive(true);
|
||||
$manager->persist($civility);
|
@ -22,6 +22,8 @@
|
||||
|
||||
namespace Chill\MainBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
@ -40,21 +42,41 @@ class LoadPostalCodes extends AbstractFixture implements OrderedFixtureInterface
|
||||
return 50;
|
||||
}
|
||||
|
||||
public static $refs = array();
|
||||
public static $refs = [];
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$lines = str_getcsv(self::$codes, "\n");
|
||||
$belgium = $manager->getRepository('ChillMainBundle:Country')
|
||||
->findOneBy(array('countryCode' => 'BE'));
|
||||
echo "loading postal codes... \n";
|
||||
$this->loadPostalCodeCSV($manager, self::$postalCodeBelgium, 'BE');
|
||||
$this->loadPostalCodeCSV($manager, self::$postalCodeFrance, 'FR');
|
||||
}
|
||||
|
||||
private function loadPostalCodeCSV(ObjectManager $manager, string $csv, string $countryCode) {
|
||||
|
||||
$lines = str_getcsv($csv, "\n");
|
||||
$country = $manager->getRepository(Country::class)
|
||||
->findOneBy(['countryCode' => $countryCode]);
|
||||
|
||||
foreach($lines as $line) {
|
||||
$code = str_getcsv($line);
|
||||
$c = new PostalCode();
|
||||
$c->setCountry($belgium)
|
||||
$c->setCountry($country)
|
||||
->setCode($code[0])
|
||||
->setName(\ucwords(\strtolower($code[2])))
|
||||
->setName(\ucwords(\strtolower($code[1])))
|
||||
;
|
||||
|
||||
if (NULL != $code[3]){
|
||||
$c->setRefPostalCodeId($code[3]);
|
||||
}
|
||||
|
||||
if (NULL != $code[4] & NULL != $code[5]){
|
||||
$c->setCenter(Point::fromLonLat((float) $code[5], (float) $code[4]));
|
||||
}
|
||||
|
||||
if (NULL != $code[6]){
|
||||
$c->setPostalCodeSource($code[6]);
|
||||
}
|
||||
|
||||
$manager->persist($c);
|
||||
$ref = 'postal_code_'.$code[0];
|
||||
|
||||
@ -66,40 +88,342 @@ class LoadPostalCodes extends AbstractFixture implements OrderedFixtureInterface
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
private static $codes = <<<EOF
|
||||
1000,BRUXELLES,BRUXELLES,Bruxelles
|
||||
1020,Laeken,BRUXELLES,Bruxelles
|
||||
1030,SCHAERBEEK,SCHAERBEEK,Bruxelles
|
||||
1040,ETTERBEEK,ETTERBEEK,Bruxelles
|
||||
1050,IXELLES,IXELLES,Bruxelles
|
||||
1060,SAINT-GILLES,SAINT-GILLES,Bruxelles
|
||||
1070,ANDERLECHT,ANDERLECHT,Bruxelles
|
||||
1080,MOLENBEEK-SAINT-JEAN,MOLENBEEK-SAINT-JEAN,Bruxelles
|
||||
1081,KOEKELBERG,KOEKELBERG,Bruxelles
|
||||
1082,BERCHEM-SAINTE-AGATHE,BERCHEM-SAINTE-AGATHE,Bruxelles
|
||||
1083,GANSHOREN,GANSHOREN,Bruxelles
|
||||
1090,JETTE,JETTE,Bruxelles
|
||||
1120,Neder-Over-Heembeek,BRUXELLES,Bruxelles
|
||||
1130,Haren,BRUXELLES,Bruxelles
|
||||
1140,EVERE,EVERE,Bruxelles
|
||||
1150,WOLUWE-SAINT-PIERRE,WOLUWE-SAINT-PIERRE,Bruxelles
|
||||
1160,AUDERGHEM,AUDERGHEM,Bruxelles
|
||||
1170,WATERMAEL-BOITSFORT,WATERMAEL-BOITSFORT,Bruxelles
|
||||
1180,UCCLE,UCCLE,Bruxelles
|
||||
1190,FOREST,FOREST,Bruxelles
|
||||
1200,WOLUWE-SAINT-LAMBERT,WOLUWE-SAINT-LAMBERT,Bruxelles
|
||||
1210,SAINT-JOSSE-TEN-NOODE,SAINT-JOSSE-TEN-NOODE,Bruxelles
|
||||
1300,Limal,WAVRE,Brabant-Wallon
|
||||
1300,WAVRE,WAVRE,Brabant-Wallon
|
||||
1301,Bierges,WAVRE,Brabant-Wallon
|
||||
1310,LA HULPE,LA HULPE,Brabant-Wallon
|
||||
1315,Glimes,INCOURT,Brabant-Wallon
|
||||
1315,INCOURT,INCOURT,Brabant-Wallon
|
||||
1315,Opprebais,INCOURT,Brabant-Wallon
|
||||
1315,Piètrebais,INCOURT,Brabant-Wallon
|
||||
1315,Roux-Miroir,INCOURT,Brabant-Wallon
|
||||
1320,BEAUVECHAIN,BEAUVECHAIN,Brabant-Wallon
|
||||
|
||||
private static $postalCodeBelgium = <<<EOF
|
||||
1000,BRUXELLES,BE
|
||||
1020,BRUXELLES,BE
|
||||
1030,SCHAERBEEK,BE
|
||||
1040,ETTERBEEK,BE
|
||||
1050,IXELLES,BE
|
||||
1060,SAINT-GILLES,BE
|
||||
1070,ANDERLECHT,BE
|
||||
1080,MOLENBEEK-SAINT-JEAN,BE
|
||||
1081,KOEKELBERG,BE
|
||||
1082,BERCHEM-SAINTE-AGATHE,BE
|
||||
1083,GANSHOREN,BE
|
||||
1090,JETTE,BE
|
||||
1120,BRUXELLES,BE
|
||||
1130,BRUXELLES,BE
|
||||
1140,EVERE,BE
|
||||
1150,WOLUWE-SAINT-PIERRE,BE
|
||||
1160,AUDERGHEM,BE
|
||||
1170,WATERMAEL-BOITSFORT,BE
|
||||
1180,UCCLE,BE
|
||||
1190,FOREST,BE
|
||||
1200,WOLUWE-SAINT-LAMBERT,BE
|
||||
1210,SAINT-JOSSE-TEN-NOODE,BE
|
||||
1300,WAVRE,BE
|
||||
1300,WAVRE,BE
|
||||
1301,WAVRE,BE
|
||||
1310,LA HULPE,BE
|
||||
1315,INCOURT,BE
|
||||
1315,INCOURT,BE
|
||||
1315,INCOURT,BE
|
||||
1315,INCOURT,BE
|
||||
1315,INCOURT,BE
|
||||
1320,BEAUVECHAIN,BE
|
||||
EOF;
|
||||
|
||||
private static $postalCodeFrance = <<<EOF
|
||||
85000,LA ROCHE SUR YON,FR,85191,46.6675261644,-1.4077954093,INSEE
|
||||
85000,MOUILLERON LE CAPTIF,FR,85155,46.7104764993,-1.46129661418,INSEE
|
||||
85100,LES SABLES D OLONNE,FR,85194,46.5007612799,-1.79255128677,INSEE
|
||||
85110,STE CECILE,FR,85202,46.7309688326,-1.12107316048,INSEE
|
||||
85110,LA JAUDONNIERE,FR,85115,46.6488761831,-0.962477574588,INSEE
|
||||
85110,ST GERMAIN DE PRINCAY,FR,85220,46.7356314659,-1.04299885081,INSEE
|
||||
85110,MONSIREIGNE,FR,85145,46.7383480028,-0.931953130855,INSEE
|
||||
85110,ST VINCENT STERLANGES,FR,85276,46.7397220689,-1.08371759277,INSEE
|
||||
85110,SIGOURNAIS,FR,85282,46.7140097406,-0.98747730882,INSEE
|
||||
85110,CHANTONNAY,FR,85051,46.6690167793,-1.04372588019,INSEE
|
||||
85110,CHANTONNAY,FR,85051,46.6690167793,-1.04372588019,INSEE
|
||||
85110,ST PROUANT,FR,85266,46.7502017421,-0.974504061491,INSEE
|
||||
85120,LA CHAPELLE AUX LYS,FR,85053,46.6221916887,-0.642706103195,INSEE
|
||||
85120,VOUVANT,FR,85305,46.5626835135,-0.764380170382,INSEE
|
||||
85120,ANTIGNY,FR,85005,46.6191770822,-0.767030058653,INSEE
|
||||
85120,ST MAURICE DES NOUES,FR,85251,46.5955876221,-0.724327725888,INSEE
|
||||
85120,LOGE FOUGEREUSE,FR,85125,46.6180854641,-0.6899276733,INSEE
|
||||
85120,LA TARDIERE,FR,85289,46.663737434,-0.727562430214,INSEE
|
||||
85120,LA CHATAIGNERAIE,FR,85059,46.6416143401,-0.739561966419,INSEE
|
||||
85120,ST HILAIRE DE VOUST,FR,85229,46.5914988312,-0.651486245674,INSEE
|
||||
85120,BREUIL BARRET,FR,85037,46.6503266235,-0.671948654426,INSEE
|
||||
85120,ST PIERRE DU CHEMIN,FR,85264,46.6957771744,-0.701777715154,INSEE
|
||||
85130,LA GAUBRETIERE,FR,85097,46.9345007303,-1.05578200702,INSEE
|
||||
85130,ST MARTIN DES TILLEULS,FR,85247,46.9711539531,-1.06282621567,INSEE
|
||||
85130,TIFFAUGES,FR,85293,47.0020573556,-1.09858009203,INSEE
|
||||
85130,CHANVERRIE,FR,85302,46.9634774521,-0.985340006089,INSEE
|
||||
85130,BAZOGES EN PAILLERS,FR,85013,46.9213757643,-1.14415666313,INSEE
|
||||
85130,LES LANDES GENUSSON,FR,85119,46.9663828627,-1.12900644447,INSEE
|
||||
85130,ST AUBIN DES ORMEAUX,FR,85198,46.9958175597,-1.04216568722,INSEE
|
||||
85140,ESSARTS EN BOCAGE,FR,85084,46.7806739038,-1.22925967851,INSEE
|
||||
85140,LA MERLATIERE,FR,85142,46.7557703112,-1.29794577,INSEE
|
||||
85140,ESSARTS EN BOCAGE,FR,85084,46.7806739038,-1.22925967851,INSEE
|
||||
85140,ESSARTS EN BOCAGE,FR,85084,46.7806739038,-1.22925967851,INSEE
|
||||
85140,ST MARTIN DES NOYERS,FR,85246,46.7239461187,-1.20379080965,INSEE
|
||||
85140,CHAUCHE,FR,85064,46.8282791899,-1.27090860656,INSEE
|
||||
85140,ESSARTS EN BOCAGE,FR,85084,46.7806739038,-1.22925967851,INSEE
|
||||
85150,ST MATHURIN,FR,85250,46.5686332748,-1.70787622288,INSEE
|
||||
85150,MARTINET,FR,85138,46.6620680463,-1.6772013304,INSEE
|
||||
85150,STE FLAIVE DES LOUPS,FR,85211,46.611019489,-1.58031627863,INSEE
|
||||
85150,STE FOY,FR,85214,46.5327600427,-1.69243074733,INSEE
|
||||
85150,ST JULIEN DES LANDES,FR,85236,46.6395925444,-1.7159724914,INSEE
|
||||
85150,ST GEORGES DE POINTINDOUX,FR,85218,46.6423470977,-1.62881823574,INSEE
|
||||
85150,LE GIROUARD,FR,85099,46.5726064909,-1.58872487716,INSEE
|
||||
85150,LANDERONDE,FR,85118,46.6549237031,-1.57351777893,INSEE
|
||||
85150,LES ACHARDS,FR,85152,46.6163645636,-1.65038156849,INSEE
|
||||
85150,LES ACHARDS,FR,85152,46.6163645636,-1.65038156849,INSEE
|
||||
85150,VAIRE,FR,85298,46.6055340621,-1.74863672042,INSEE
|
||||
85160,ST JEAN DE MONTS,FR,85234,46.8021968737,-2.04839789308,INSEE
|
||||
85170,BELLEVIGNY,FR,85019,46.7756383534,-1.43313700054,INSEE
|
||||
85170,LE POIRE SUR VIE,FR,85178,46.769919754,-1.50488626452,INSEE
|
||||
85170,BEAUFOU,FR,85015,46.8191122027,-1.52479250801,INSEE
|
||||
85170,DOMPIERRE SUR YON,FR,85081,46.7599858068,-1.37275519417,INSEE
|
||||
85170,BELLEVIGNY,FR,85019,46.7756383534,-1.43313700054,INSEE
|
||||
85170,LES LUCS SUR BOULOGNE,FR,85129,46.8527299002,-1.48398928084,INSEE
|
||||
85170,ST DENIS LA CHEVASSE,FR,85208,46.8325959261,-1.3830312677,INSEE
|
||||
85180,LES SABLES D OLONNE,FR,85194,46.5007612799,-1.79255128677,INSEE
|
||||
85190,AIZENAY,FR,85003,46.7384516809,-1.62702889721,INSEE
|
||||
85190,VENANSAULT,FR,85300,46.685677363,-1.54112129191,INSEE
|
||||
85190,MACHE,FR,85130,46.771364944,-1.69526445062,INSEE
|
||||
85190,BEAULIEU SOUS LA ROCHE,FR,85016,46.6872087211,-1.62355064963,INSEE
|
||||
85190,LA GENETOUZE,FR,85098,46.7244524541,-1.50410719693,INSEE
|
||||
85200,PISSOTTE,FR,85176,46.5010870694,-0.808352236192,INSEE
|
||||
85200,AUCHAY SUR VENDEE,FR,85009,46.4474386161,-0.876574265149,INSEE
|
||||
85200,FONTENAY LE COMTE,FR,85092,46.4563186117,-0.793449510859,INSEE
|
||||
85200,MERVENT,FR,85143,46.5325327351,-0.748519927998,INSEE
|
||||
85200,DOIX LES FONTAINES,FR,85080,46.3849492327,-0.806840287485,INSEE
|
||||
85200,FONTENAY LE COMTE,FR,85092,46.4563186117,-0.793449510859,INSEE
|
||||
85200,LONGEVES,FR,85126,46.4722105292,-0.858917690239,INSEE
|
||||
85200,ST MARTIN DE FRAIGNEAU,FR,85244,46.4289052087,-0.758948963227,INSEE
|
||||
85200,SERIGNE,FR,85281,46.5054321828,-0.848819460581,INSEE
|
||||
85200,BOURNEAU,FR,85033,46.5476882922,-0.813838020265,INSEE
|
||||
85200,ST MICHEL LE CLOUCQ,FR,85256,46.4861591475,-0.743056336646,INSEE
|
||||
85200,AUCHAY SUR VENDEE,FR,85009,46.4474386161,-0.876574265149,INSEE
|
||||
85200,DOIX LES FONTAINES,FR,85080,46.3849492327,-0.806840287485,INSEE
|
||||
85200,MONTREUIL,FR,85148,46.3973419593,-0.840846860992,INSEE
|
||||
85200,L ORBRIE,FR,85167,46.4997145725,-0.77427886573,INSEE
|
||||
85210,ST JEAN DE BEUGNE,FR,85233,46.5196817523,-1.10826075013,INSEE
|
||||
85210,ST MARTIN LARS EN STE HERMINE,FR,85248,46.5970244335,-0.976384286709,INSEE
|
||||
85210,LA REORTHE,FR,85188,46.6113748938,-1.04881036553,INSEE
|
||||
85210,ST AUBIN LA PLAINE,FR,85199,46.5040293195,-1.06506577005,INSEE
|
||||
85210,ST JUIRE CHAMPGILLON,FR,85235,46.5882648491,-1.00959676911,INSEE
|
||||
85210,LA CHAPELLE THEMER,FR,85056,46.5639307793,-0.960376685588,INSEE
|
||||
85210,ST ETIENNE DE BRILLOUET,FR,85209,46.5138850327,-1.01157660374,INSEE
|
||||
85210,STE HERMINE,FR,85223,46.5572659953,-1.07210861039,INSEE
|
||||
85210,THIRE,FR,85290,46.5433098199,-1.00699777534,INSEE
|
||||
85220,ST MAIXENT SUR VIE,FR,85239,46.7329496925,-1.82595152879,INSEE
|
||||
85220,LA CHAIZE GIRAUD,FR,85045,46.6476375058,-1.81865076161,INSEE
|
||||
85220,LANDEVIEILLE,FR,85120,46.6444349925,-1.7854367847,INSEE
|
||||
85220,L AIGUILLON SUR VIE,FR,85002,46.6706426618,-1.82599992318,INSEE
|
||||
85220,COEX,FR,85070,46.7078707764,-1.75788339462,INSEE
|
||||
85220,ST REVEREND,FR,85268,46.7057741864,-1.83155480996,INSEE
|
||||
85220,APREMONT,FR,85006,46.7572682339,-1.74841313647,INSEE
|
||||
85220,LA CHAPELLE HERMIER,FR,85054,46.6826679204,-1.72083372442,INSEE
|
||||
85220,COMMEQUIERS,FR,85071,46.7674752232,-1.82534079642,INSEE
|
||||
85230,BEAUVOIR SUR MER,FR,85018,46.9086155426,-2.06349351302,INSEE
|
||||
85230,BOUIN,FR,85029,46.9815930867,-2.00423808381,INSEE
|
||||
85230,ST URBAIN,FR,85273,46.8818371328,-2.01607828912,INSEE
|
||||
85230,ST GERVAIS,FR,85221,46.9285711589,-1.98059327519,INSEE
|
||||
85240,MARILLET,FR,85136,46.5667525381,-0.634287713939,INSEE
|
||||
85240,ST HILAIRE DES LOGES,FR,85227,46.4747117878,-0.650611151998,INSEE
|
||||
85240,FAYMOREAU,FR,85087,46.5427361252,-0.624271378946,INSEE
|
||||
85240,XANTON CHASSENON,FR,85306,46.4519408659,-0.706316598666,INSEE
|
||||
85240,FOUSSAIS PAYRE,FR,85094,46.5230750581,-0.687135962627,INSEE
|
||||
85240,RIVES D AUTISE,FR,85162,46.424726987,-0.665995249042,INSEE
|
||||
85240,PUY DE SERRE,FR,85184,46.5650384637,-0.680144631346,INSEE
|
||||
85250,ST ANDRE GOULE D OIE,FR,85196,46.8410224478,-1.19644211396,INSEE
|
||||
85250,LA RABATELIERE,FR,85186,46.8584147661,-1.2569733759,INSEE
|
||||
85250,CHAVAGNES EN PAILLERS,FR,85065,46.8951394423,-1.24054768713,INSEE
|
||||
85250,ST FULGENT,FR,85215,46.8705618525,-1.16246465678,INSEE
|
||||
85250,VENDRENNES,FR,85301,46.8226741756,-1.11650982164,INSEE
|
||||
85260,LA COPECHAGNIERE,FR,85072,46.8523980181,-1.34349746898,INSEE
|
||||
85260,L HERBERGEMENT,FR,85108,46.9166207979,-1.37033557148,INSEE
|
||||
85260,MONTREVERD,FR,85197,46.9277672307,-1.4126154924,INSEE
|
||||
85260,MONTREVERD,FR,85197,46.9277672307,-1.4126154924,INSEE
|
||||
85260,MONTREVERD,FR,85197,46.9277672307,-1.4126154924,INSEE
|
||||
85260,LES BROUZILS,FR,85038,46.8854235235,-1.33186892233,INSEE
|
||||
85270,NOTRE DAME DE RIEZ,FR,85189,46.7532179022,-1.8935292542,INSEE
|
||||
85270,ST HILAIRE DE RIEZ,FR,85226,46.7432732188,-1.96439228965,INSEE
|
||||
85270,ST HILAIRE DE RIEZ,FR,85226,46.7432732188,-1.96439228965,INSEE
|
||||
85280,LA FERRIERE,FR,85089,46.7215872927,-1.33469332327,INSEE
|
||||
85290,MORTAGNE SUR SEVRE,FR,85151,46.9910941319,-0.946500033344,INSEE
|
||||
85290,ST LAURENT SUR SEVRE,FR,85238,46.9506837971,-0.901123752328,INSEE
|
||||
85300,CHALLANS,FR,85047,46.8354416653,-1.84036683139,INSEE
|
||||
85300,FROIDFOND,FR,85095,46.8789464367,-1.75511438567,INSEE
|
||||
85300,SOULLANS,FR,85284,46.7951288466,-1.91392699457,INSEE
|
||||
85300,LE PERRIER,FR,85172,46.8196487652,-1.97926629071,INSEE
|
||||
85300,SALLERTAINE,FR,85280,46.8659054157,-1.94894081389,INSEE
|
||||
85310,LA CHAIZE LE VICOMTE,FR,85046,46.6729533879,-1.29188591019,INSEE
|
||||
85310,NESMY,FR,85160,46.5921936479,-1.40947698594,INSEE
|
||||
85310,LA CHAIZE LE VICOMTE,FR,85046,46.6729533879,-1.29188591019,INSEE
|
||||
85310,RIVES DE L YON,FR,85213,46.605637391,-1.3354497172,INSEE
|
||||
85310,RIVES DE L YON,FR,85213,46.605637391,-1.3354497172,INSEE
|
||||
85310,LE TABLIER,FR,85285,46.5596307281,-1.32788759657,INSEE
|
||||
85320,CHATEAU GUIBERT,FR,85061,46.5741109302,-1.25524886228,INSEE
|
||||
85320,LES PINEAUX,FR,85175,46.599225902,-1.17865799724,INSEE
|
||||
85320,ROSNAY,FR,85193,46.5324344973,-1.3007139449,INSEE
|
||||
85320,BESSAY,FR,85023,46.5397253861,-1.17028433093,INSEE
|
||||
85320,LA BRETONNIERE LA CLAYE,FR,85036,46.4879459421,-1.26773426545,INSEE
|
||||
85320,LA BRETONNIERE LA CLAYE,FR,85036,46.4879459421,-1.26773426545,INSEE
|
||||
85320,CORPE,FR,85073,46.5050234767,-1.17034425311,INSEE
|
||||
85320,MAREUIL SUR LAY DISSAIS,FR,85135,46.5335825488,-1.22688907859,INSEE
|
||||
85320,PEAULT,FR,85171,46.502029199,-1.22708559855,INSEE
|
||||
85320,MAREUIL SUR LAY DISSAIS,FR,85135,46.5335825488,-1.22688907859,INSEE
|
||||
85320,LA COUTURE,FR,85074,46.523938732,-1.26493227292,INSEE
|
||||
85320,MOUTIERS SUR LE LAY,FR,85157,46.5651677306,-1.16826489836,INSEE
|
||||
85320,STE PEXINE,FR,85261,46.5596018797,-1.12406235901,INSEE
|
||||
85330,NOIRMOUTIER EN L ILE,FR,85163,47.0086655085,-2.26243620205,INSEE
|
||||
85340,L ILE D OLONNE,FR,85112,46.570163703,-1.7737502368,INSEE
|
||||
85340,LES SABLES D OLONNE,FR,85194,46.5007612799,-1.79255128677,INSEE
|
||||
85350,L ILE D YEU,FR,85113,46.7093514816,-2.34712702345,INSEE
|
||||
85350,L ILE D YEU,FR,85113,46.7093514816,-2.34712702345,INSEE
|
||||
85360,LA TRANCHE SUR MER,FR,85294,46.3564601605,-1.43136322126,INSEE
|
||||
85370,MOUZEUIL ST MARTIN,FR,85158,46.4591118412,-0.984449849889,INSEE
|
||||
85370,NALLIERS,FR,85159,46.4658962703,-1.03958611312,INSEE
|
||||
85370,LE LANGON,FR,85121,46.4393119039,-0.947017086151,INSEE
|
||||
85390,BAZOGES EN PAREDS,FR,85014,46.6602005512,-0.914053446792,INSEE
|
||||
85390,ST MAURICE LE GIRARD,FR,85252,46.6398624578,-0.810875649028,INSEE
|
||||
85390,TALLUD STE GEMME,FR,85287,46.6949386862,-0.886169517112,INSEE
|
||||
85390,CHAVAGNES LES REDOUX,FR,85066,46.7101499475,-0.915900131393,INSEE
|
||||
85390,CHEFFOIS,FR,85067,46.6786935635,-0.782949851125,INSEE
|
||||
85390,MOUILLERON ST GERMAIN,FR,85154,46.6612700667,-0.846784201071,INSEE
|
||||
85390,MOUILLERON ST GERMAIN,FR,85154,46.6612700667,-0.846784201071,INSEE
|
||||
85400,STE GEMME LA PLAINE,FR,85216,46.4732196212,-1.11103084694,INSEE
|
||||
85400,LAIROUX,FR,85117,46.4496842668,-1.27114022202,INSEE
|
||||
85400,LUCON,FR,85128,46.4510564854,-1.16449285012,INSEE
|
||||
85400,LES MAGNILS REIGNIERS,FR,85131,46.4635045649,-1.210635375,INSEE
|
||||
85400,CHASNAIS,FR,85058,46.4459908481,-1.2385924923,INSEE
|
||||
85410,ST LAURENT DE LA SALLE,FR,85237,46.5854041653,-0.922177315485,INSEE
|
||||
85410,LA CAILLERE ST HILAIRE,FR,85040,46.6293907412,-0.933153931505,INSEE
|
||||
85410,LA CAILLERE ST HILAIRE,FR,85040,46.6293907412,-0.933153931505,INSEE
|
||||
85410,ST CYR DES GATS,FR,85205,46.572397925,-0.86344873853,INSEE
|
||||
85410,THOUARSAIS BOUILDROUX,FR,85292,46.6062740621,-0.873461023865,INSEE
|
||||
85410,CEZAIS,FR,85041,46.5917363748,-0.802618133558,INSEE
|
||||
85410,ST SULPICE EN PAREDS,FR,85271,46.6130038733,-0.8310839288,INSEE
|
||||
85420,LE MAZEAU,FR,85139,46.3298580373,-0.672957405035,INSEE
|
||||
85420,LIEZ,FR,85123,46.3698532376,-0.70502476758,INSEE
|
||||
85420,BOUILLE COURDAULT,FR,85028,46.3847932448,-0.684917815779,INSEE
|
||||
85420,DAMVIX,FR,85078,46.32063079,-0.743504259797,INSEE
|
||||
85420,MAILLE,FR,85132,46.3417503082,-0.787487297301,INSEE
|
||||
85420,ST PIERRE LE VIEUX,FR,85265,46.4009643491,-0.742816267425,INSEE
|
||||
85420,ST SIGISMOND,FR,85269,46.3368577973,-0.707293731101,INSEE
|
||||
85420,MAILLEZAIS,FR,85133,46.3642178261,-0.750260780443,INSEE
|
||||
85420,RIVES D AUTISE,FR,85162,46.424726987,-0.665995249042,INSEE
|
||||
85430,AUBIGNY LES CLOUZEAUX,FR,85008,46.6028241769,-1.46743549114,INSEE
|
||||
85430,NIEUL LE DOLENT,FR,85161,46.5676509922,-1.51560194548,INSEE
|
||||
85430,AUBIGNY LES CLOUZEAUX,FR,85008,46.6028241769,-1.46743549114,INSEE
|
||||
85430,LA BOISSIERE DES LANDES,FR,85026,46.5581861734,-1.44371985689,INSEE
|
||||
85440,ST HILAIRE LA FORET,FR,85231,46.4551155186,-1.53048160541,INSEE
|
||||
85440,TALMONT ST HILAIRE,FR,85288,46.475786445,-1.62751498166,INSEE
|
||||
85440,POIROUX,FR,85179,46.5107890457,-1.53929317556,INSEE
|
||||
85440,GROSBREUIL,FR,85103,46.5390090882,-1.6072005484,INSEE
|
||||
85440,AVRILLE,FR,85010,46.4744272125,-1.49524360118,INSEE
|
||||
85440,TALMONT ST HILAIRE,FR,85288,46.475786445,-1.62751498166,INSEE
|
||||
85450,CHAMPAGNE LES MARAIS,FR,85049,46.3735020647,-1.13380723653,INSEE
|
||||
85450,LA TAILLEE,FR,85286,46.3852513569,-0.941017792066,INSEE
|
||||
85450,CHAILLE LES MARAIS,FR,85042,46.3853555319,-1.01044079362,INSEE
|
||||
85450,CHAILLE LES MARAIS,FR,85042,46.3853555319,-1.01044079362,INSEE
|
||||
85450,VOUILLE LES MARAIS,FR,85304,46.3891941167,-0.968106001439,INSEE
|
||||
85450,CHAILLE LES MARAIS,FR,85042,46.3853555319,-1.01044079362,INSEE
|
||||
85450,MOREILLES,FR,85149,46.4218721314,-1.09404530407,INSEE
|
||||
85450,PUYRAVAULT,FR,85185,46.3653834101,-1.09115660367,INSEE
|
||||
85450,STE RADEGONDE DES NOYERS,FR,85267,46.3694246909,-1.06671995264,INSEE
|
||||
85460,LA FAUTE SUR MER,FR,85307,46.3199919131,-1.31487049579,INSEE
|
||||
85460,L AIGUILLON SUR MER,FR,85001,46.304138479,-1.2623239198,INSEE
|
||||
85470,BRETIGNOLLES SUR MER,FR,85035,46.6374826705,-1.86324200464,INSEE
|
||||
85470,BREM SUR MER,FR,85243,46.6118566989,-1.81003917923,INSEE
|
||||
85470,BREM SUR MER,FR,85243,46.6118566989,-1.81003917923,INSEE
|
||||
85480,BOURNEZEAU,FR,85034,46.6296975315,-1.14101742229,INSEE
|
||||
85480,FOUGERE,FR,85093,46.6617881911,-1.23612691916,INSEE
|
||||
85480,ST HILAIRE LE VOUHIS,FR,85232,46.6859198669,-1.15222590884,INSEE
|
||||
85480,THORIGNY,FR,85291,46.6179795025,-1.24888057642,INSEE
|
||||
85480,BOURNEZEAU,FR,85034,46.6296975315,-1.14101742229,INSEE
|
||||
85490,BENET,FR,85020,46.368873213,-0.613959918706,INSEE
|
||||
85490,BENET,FR,85020,46.368873213,-0.613959918706,INSEE
|
||||
85490,BENET,FR,85020,46.368873213,-0.613959918706,INSEE
|
||||
85500,BEAUREPAIRE,FR,85017,46.9050210355,-1.10144867013,INSEE
|
||||
85500,ST PAUL EN PAREDS,FR,85259,46.8303789022,-0.964515191283,INSEE
|
||||
85500,LES HERBIERS,FR,85109,46.8666125813,-1.02216086186,INSEE
|
||||
85500,MESNARD LA BAROTIERE,FR,85144,46.851716793,-1.10954466033,INSEE
|
||||
85500,CHANVERRIE,FR,85302,46.9634774521,-0.985340006089,INSEE
|
||||
85510,ROCHETREJOUX,FR,85192,46.7852546732,-0.996743019108,INSEE
|
||||
85510,LE BOUPERE,FR,85031,46.7877960262,-0.930897406714,INSEE
|
||||
85520,JARD SUR MER,FR,85114,46.4246376808,-1.60014921643,INSEE
|
||||
85520,ST VINCENT SUR JARD,FR,85278,46.4297504489,-1.54956205778,INSEE
|
||||
85530,LA BRUFFIERE,FR,85039,47.0148006973,-1.18329758318,INSEE
|
||||
85540,LE CHAMP ST PERE,FR,85050,46.5157210212,-1.33946630196,INSEE
|
||||
85540,LE GIVRE,FR,85101,46.4729146043,-1.40256149118,INSEE
|
||||
85540,MOUTIERS LES MAUXFAITS,FR,85156,46.489279204,-1.43622387207,INSEE
|
||||
85540,ST VINCENT SUR GRAON,FR,85277,46.5034756656,-1.382954206,INSEE
|
||||
85540,LA JONCHERE,FR,85116,46.4358647401,-1.38517843312,INSEE
|
||||
85540,ST BENOIST SUR MER,FR,85201,46.4266286403,-1.3399129604,INSEE
|
||||
85540,ST VINCENT SUR GRAON,FR,85277,46.5034756656,-1.382954206,INSEE
|
||||
85540,CURZON,FR,85077,46.4512376923,-1.30138059216,INSEE
|
||||
85540,ST AVAUGOURD DES LANDES,FR,85200,46.5136722903,-1.47528120789,INSEE
|
||||
85540,ST CYR EN TALMONDAIS,FR,85206,46.4597334032,-1.33722144355,INSEE
|
||||
85550,LA BARRE DE MONTS,FR,85012,46.8722784154,-2.09984018879,INSEE
|
||||
85550,LA BARRE DE MONTS,FR,85012,46.8722784154,-2.09984018879,INSEE
|
||||
85560,LE BERNARD,FR,85022,46.44832528,-1.43979865314,INSEE
|
||||
85560,LONGEVILLE SUR MER,FR,85127,46.4091029013,-1.47711855345,INSEE
|
||||
85570,POUILLE,FR,85181,46.5022256779,-0.955223380119,INSEE
|
||||
85570,ST VALERIEN,FR,85274,46.5348508899,-0.944470507825,INSEE
|
||||
85570,L HERMENAULT,FR,85110,46.5156262822,-0.898430664265,INSEE
|
||||
85570,PETOSSE,FR,85174,46.4796848965,-0.911734176662,INSEE
|
||||
85570,ST MARTIN DES FONTAINES,FR,85245,46.5464637508,-0.907394581139,INSEE
|
||||
85570,MARSAIS STE RADEGONDE,FR,85137,46.5380790745,-0.868868309437,INSEE
|
||||
85580,ST DENIS DU PAYRE,FR,85207,46.4118936776,-1.27222282402,INSEE
|
||||
85580,ST MICHEL EN L HERM,FR,85255,46.3366903175,-1.2483968538,INSEE
|
||||
85580,TRIAIZE,FR,85297,46.3792685111,-1.19928351422,INSEE
|
||||
85580,GRUES,FR,85104,46.3813091348,-1.32364519268,INSEE
|
||||
85590,TREIZE VENTS,FR,85296,46.9168130123,-0.845959158017,INSEE
|
||||
85590,LES EPESSES,FR,85082,46.8917166066,-0.903422756546,INSEE
|
||||
85590,MALLIEVRE,FR,85134,46.9112847287,-0.864977836096,INSEE
|
||||
85590,ST MALO DU BOIS,FR,85240,46.9248120291,-0.914182961099,INSEE
|
||||
85590,ST MARS LA REORTHE,FR,85242,46.8597253005,-0.925777900202,INSEE
|
||||
85600,LA BOISSIERE DE MONTAIGU,FR,85025,46.9451858636,-1.1916392484,INSEE
|
||||
85600,MONTAIGU VENDEE,FR,85146,46.9759800852,-1.31364530268,INSEE
|
||||
85600,MONTAIGU VENDEE,FR,85146,46.9759800852,-1.31364530268,INSEE
|
||||
85600,TREIZE SEPTIERS,FR,85295,46.9975586143,-1.23193361154,INSEE
|
||||
85600,MONTAIGU VENDEE,FR,85146,46.9759800852,-1.31364530268,INSEE
|
||||
85600,MONTAIGU VENDEE,FR,85146,46.9759800852,-1.31364530268,INSEE
|
||||
85600,MONTAIGU VENDEE,FR,85146,46.9759800852,-1.31364530268,INSEE
|
||||
85610,CUGAND,FR,85076,47.0602388146,-1.25289811103,INSEE
|
||||
85610,LA BERNARDIERE,FR,85021,47.0361828072,-1.27390355206,INSEE
|
||||
85620,ROCHESERVIERE,FR,85190,46.9274273036,-1.50132208111,INSEE
|
||||
85630,BARBATRE,FR,85011,46.9335754783,-2.16743559847,INSEE
|
||||
85640,MOUCHAMPS,FR,85153,46.7870550926,-1.05454102867,INSEE
|
||||
85660,ST PHILBERT DE BOUAINE,FR,85262,46.9927907526,-1.5073882242,INSEE
|
||||
85670,LA CHAPELLE PALLUAU,FR,85055,46.7873638997,-1.62492863273,INSEE
|
||||
85670,FALLERON,FR,85086,46.8623928354,-1.70108938038,INSEE
|
||||
85670,ST ETIENNE DU BOIS,FR,85210,46.8418481774,-1.59617737479,INSEE
|
||||
85670,ST PAUL MONT PENIT,FR,85260,46.8070059547,-1.66964833149,INSEE
|
||||
85670,ST CHRISTOPHE DU LIGNERON,FR,85204,46.8151386519,-1.74035413493,INSEE
|
||||
85670,GRAND LANDES,FR,85102,46.8483283063,-1.64453002578,INSEE
|
||||
85670,PALLUAU,FR,85169,46.8063002019,-1.60225256402,INSEE
|
||||
85680,LA GUERINIERE,FR,85106,46.9669962053,-2.2302799245,INSEE
|
||||
85690,NOTRE DAME DE MONTS,FR,85164,46.8424284611,-2.10928732775,INSEE
|
||||
85700,SEVREMONT,FR,85090,46.8211105864,-0.854584153953,INSEE
|
||||
85700,LA MEILLERAIE TILLAY,FR,85140,46.742582825,-0.85478763606,INSEE
|
||||
85700,MONTOURNAIS,FR,85147,46.7502937556,-0.770013941158,INSEE
|
||||
85700,POUZAUGES,FR,85182,46.7812581702,-0.828778359084,INSEE
|
||||
85700,REAUMUR,FR,85187,46.7145137269,-0.816742537248,INSEE
|
||||
85700,SEVREMONT,FR,85090,46.8211105864,-0.854584153953,INSEE
|
||||
85700,MENOMBLET,FR,85141,46.7301338667,-0.728654955878,INSEE
|
||||
85700,ST MESMIN,FR,85254,46.8005779435,-0.748892533741,INSEE
|
||||
85700,SEVREMONT,FR,85090,46.8211105864,-0.854584153953,INSEE
|
||||
85700,SEVREMONT,FR,85090,46.8211105864,-0.854584153953,INSEE
|
||||
85710,BOIS DE CENE,FR,85024,46.9479643351,-1.89668693466,INSEE
|
||||
85710,CHATEAUNEUF,FR,85062,46.916944435,-1.9261131832,INSEE
|
||||
85710,LA GARNACHE,FR,85096,46.8977541296,-1.82443040539,INSEE
|
||||
85740,L EPINE,FR,85083,46.9843405667,-2.26449527608,INSEE
|
||||
85750,ANGLES,FR,85004,46.3870511077,-1.40049386944,INSEE
|
||||
85770,LES VELLUIRE SUR VENDEE,FR,85177,46.4190919441,-0.910475769222,INSEE
|
||||
85770,VIX,FR,85303,46.3543018169,-0.856628326667,INSEE
|
||||
85770,LE GUE DE VELLUIRE,FR,85105,46.3675950645,-0.905432724485,INSEE
|
||||
85770,L ILE D ELLE,FR,85111,46.3334258655,-0.919100677098,INSEE
|
||||
85770,LES VELLUIRE SUR VENDEE,FR,85177,46.4190919441,-0.910475769222,INSEE
|
||||
85800,ST GILLES CROIX DE VIE,FR,85222,46.6904708814,-1.91946363327,INSEE
|
||||
85800,LE FENOUILLER,FR,85088,46.7161264566,-1.89206667498,INSEE
|
||||
85800,GIVRAND,FR,85100,46.6822701061,-1.8787272243,INSEE
|
||||
EOF;
|
||||
|
||||
}
|
||||
|
@ -20,33 +20,41 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\ThirdPartyBundle\Entity;
|
||||
namespace Chill\MainBundle\Entity;
|
||||
|
||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyCivilityRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="chill_3party.party_civility")
|
||||
* @ORM\Entity(repositoryClass=ThirdPartyCivilityRepository::class)
|
||||
* @ORM\Table(name="chill_main_civility")
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class ThirdPartyCivility
|
||||
class Civility
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
* @Serializer\Groups({"read"})
|
||||
*/
|
||||
private $name = [];
|
||||
private array $name = [];
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
* @Serializer\Groups({"read"})
|
||||
*/
|
||||
private array $abbreviation = [];
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
private bool $active = true;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
@ -76,4 +84,22 @@ class ThirdPartyCivility
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAbbreviation(): array
|
||||
{
|
||||
return $this->abbreviation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $abbreviation
|
||||
* @return Civility
|
||||
*/
|
||||
public function setAbbreviation(array $abbreviation): self
|
||||
{
|
||||
$this->abbreviation = $abbreviation;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Chill\MainBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
@ -62,6 +63,30 @@ class PostalCode
|
||||
*/
|
||||
private $origin = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
* @groups({"read"})
|
||||
*/
|
||||
private $refPostalCodeId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
* @groups({"read"})
|
||||
*/
|
||||
private $postalCodeSource;
|
||||
|
||||
/**
|
||||
* @var Point
|
||||
*
|
||||
* @ORM\Column(type="point", nullable=true)
|
||||
* @groups({"read"})
|
||||
*/
|
||||
private $center;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
@ -169,5 +194,41 @@ class PostalCode
|
||||
{
|
||||
return $this->country;
|
||||
}
|
||||
|
||||
public function getRefPostalCodeId(): ?string
|
||||
{
|
||||
return $this->refPostalCodeId;
|
||||
}
|
||||
|
||||
public function setRefPostalCodeId(?string $refPostalCodeId): self
|
||||
{
|
||||
$this->refPostalCodeId = $refPostalCodeId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPostalCodeSource(): ?string
|
||||
{
|
||||
return $this->postalCodeSource;
|
||||
}
|
||||
|
||||
public function setPostalCodeSource(?string $postalCodeSource): self
|
||||
{
|
||||
$this->postalCodeSource = $postalCodeSource;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCenter(): ?Point
|
||||
{
|
||||
return $this->center;
|
||||
}
|
||||
|
||||
public function setCenter(?Point $center): self
|
||||
{
|
||||
$this->center = $center;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CenterType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* The user linked with this type.
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* associative array where keys are center.id and
|
||||
* value are center objects
|
||||
*
|
||||
* @var Center[]
|
||||
*/
|
||||
protected $reachableCenters = array();
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CenterTransformer
|
||||
*/
|
||||
protected $transformer;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage,
|
||||
CenterTransformer $transformer)
|
||||
{
|
||||
$this->user = $tokenStorage->getToken()->getUser();
|
||||
$this->transformer = $transformer;
|
||||
$this->prepareReachableCenterByUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* return a 'hidden' field if only one center is available.
|
||||
*
|
||||
* Return a 'choice' field if more than one center is available.
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException if the user is not associated with any center
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
$nbReachableCenters = count($this->reachableCenters);
|
||||
|
||||
if ($nbReachableCenters <= 1) {
|
||||
return HiddenType::class;
|
||||
} else {
|
||||
return EntityType::class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* configure default options, i.e. add choices if user can reach multiple
|
||||
* centers.
|
||||
*
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
if (count($this->reachableCenters) > 1) {
|
||||
$resolver->setDefault('class', Center::class)
|
||||
->setDefault('choices', $this->reachableCenters)
|
||||
->setDefault('placeholder', 'Pick a center')
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* add a data transformer if user can reach only one center
|
||||
*
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($this->getParent() === HiddenType::class) {
|
||||
$builder->addModelTransformer($this->transformer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* populate reachableCenters as an associative array where
|
||||
* keys are center.id and value are center entities.
|
||||
*
|
||||
*/
|
||||
private function prepareReachableCenterByUser()
|
||||
{
|
||||
$groupCenters = $this->user->getGroupCenters();
|
||||
|
||||
foreach ($groupCenters as $groupCenter) {
|
||||
|
||||
$center = $groupCenter->getCenter();
|
||||
|
||||
if (!array_key_exists($center->getId(),
|
||||
$this->reachableCenters)) {
|
||||
$this->reachableCenters[$center->getId()] = $center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -24,14 +24,14 @@ use Symfony\Component\Form\FormInterface;
|
||||
|
||||
/**
|
||||
* Available options :
|
||||
*
|
||||
*
|
||||
* - `button_add_label`
|
||||
* - `button_remove_label`
|
||||
* - `identifier`: an identifier to identify the kind of collecton. Useful if some
|
||||
* javascript should be launched associated to `add_entry`, `remove_entry` events.
|
||||
*
|
||||
* - `empty_collection_explain`
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ChillCollectionType extends AbstractType
|
||||
{
|
||||
@ -41,10 +41,11 @@ class ChillCollectionType extends AbstractType
|
||||
->setDefaults([
|
||||
'button_add_label' => 'Add an entry',
|
||||
'button_remove_label' => 'Remove entry',
|
||||
'identifier' => ''
|
||||
'identifier' => '',
|
||||
'empty_collection_explain' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
$view->vars['button_add_label'] = $options['button_add_label'];
|
||||
@ -52,8 +53,9 @@ class ChillCollectionType extends AbstractType
|
||||
$view->vars['allow_delete'] = (int) $options['allow_delete'];
|
||||
$view->vars['allow_add'] = (int) $options['allow_add'];
|
||||
$view->vars['identifier'] = $options['identifier'];
|
||||
$view->vars['empty_collection_explain'] = $options['empty_collection_explain'];
|
||||
}
|
||||
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return \Symfony\Component\Form\Extension\Core\Type\CollectionType::class;
|
||||
|
@ -20,36 +20,57 @@
|
||||
namespace Chill\MainBundle\Form\Type\DataTransformer;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Repository\CenterRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
class CenterTransformer implements DataTransformerInterface
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
private CenterRepository $centerRepository;
|
||||
private bool $multiple = false;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
public function __construct(
|
||||
CenterRepository $centerRepository,
|
||||
bool $multiple = false
|
||||
) {
|
||||
$this->centerRepository = $centerRepository;
|
||||
$this->multiple = $multiple;
|
||||
}
|
||||
|
||||
public function reverseTransform($id)
|
||||
{
|
||||
if ($id === NULL) {
|
||||
return NULL;
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollection();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$center = $this
|
||||
->em
|
||||
->getRepository(Center::class)
|
||||
->find($id);
|
||||
if ($this->multiple) {
|
||||
$ids = \explode(',', $id);
|
||||
} else {
|
||||
$ids[] = (int) $id;
|
||||
}
|
||||
|
||||
if ($center === NULL) {
|
||||
$centers = $this
|
||||
->centerRepository
|
||||
->findBy(['id' => $ids ]);
|
||||
|
||||
if ([] === $centers || count($ids) > count($centers)) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'No center found with id %d', $id));
|
||||
'No center found for one of those ids: %s', implode(',', $ids)));
|
||||
}
|
||||
|
||||
return $center;
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollection($centers);
|
||||
} else {
|
||||
return $centers[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function transform($center)
|
||||
@ -58,7 +79,21 @@ class CenterTransformer implements DataTransformerInterface
|
||||
return '';
|
||||
}
|
||||
|
||||
return $center->getId();
|
||||
}
|
||||
if ($this->multiple) {
|
||||
if (!is_iterable($center)) {
|
||||
throw new UnexpectedTypeException($center, \Traversable::class);
|
||||
}
|
||||
$ids = [];
|
||||
foreach ($center as $c) {
|
||||
$ids[] = $c->getId();
|
||||
}
|
||||
|
||||
return implode(',', $ids);
|
||||
} else {
|
||||
if (!$center instanceof Center) {
|
||||
throw new UnexpectedTypeException($center, Center::class);
|
||||
}
|
||||
return (string) $center->getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Form\Type\Listing;
|
||||
|
||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SearchType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
final class FilterOrderType extends \Symfony\Component\Form\AbstractType
|
||||
{
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
/** @var FilterOrderHelper $helper */
|
||||
$helper = $options['helper'];
|
||||
|
||||
if ($helper->hasSearchBox()) {
|
||||
$builder->add('q', SearchType::class, [
|
||||
'label' => false,
|
||||
'required' => false
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($this->requestStack->getCurrentRequest()->query->getIterator() as $key => $value) {
|
||||
switch($key) {
|
||||
case 'q':
|
||||
continue;
|
||||
case 'page':
|
||||
$builder->add($key, HiddenType::class, [
|
||||
'data' => 1
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
$builder->add($key, HiddenType::class, [
|
||||
'data' => $value
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setRequired('helper')
|
||||
->setAllowedTypes('helper', FilterOrderHelper::class);
|
||||
}
|
||||
}
|
174
src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php
Normal file
174
src/Bundle/ChillMainBundle/Form/Type/PickCenterType.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\Form\Type;
|
||||
|
||||
use Chill\MainBundle\Repository\CenterRepository;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Pick a center
|
||||
*
|
||||
* For a given role and, eventually, scopes, show a dropdown (if more than
|
||||
* one reachable center) or a HiddenType (if one or zero center).
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PickCenterType extends AbstractType
|
||||
{
|
||||
protected AuthorizationHelperInterface $authorizationHelper;
|
||||
|
||||
protected Security $security;
|
||||
|
||||
protected CenterRepository $centerRepository;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelperInterface $authorizationHelper,
|
||||
Security $security,
|
||||
CenterRepository $centerRepository
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->security = $security;
|
||||
$this->centerRepository = $centerRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a 'hidden' field if only one center is available.
|
||||
*
|
||||
* Return a 'choice' field if more than one center is available.
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException if the user is not associated with any center
|
||||
*/
|
||||
/*
|
||||
public function getParent()
|
||||
{
|
||||
$nbReachableCenters = count($this->reachableCenters);
|
||||
|
||||
if ($nbReachableCenters <= 1) {
|
||||
return HiddenType::class;
|
||||
} else {
|
||||
return EntityType::class;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* configure default options, i.e. add choices if user can reach multiple
|
||||
* centers.
|
||||
*
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setDefault('class', Center::class)
|
||||
->setRequired('role')
|
||||
->setAllowedTypes('role', [ 'string' ])
|
||||
->setDefault('scopes', [])
|
||||
->setAllowedTypes('scopes', ['iterable'])
|
||||
->setDefault('choice_options', [])
|
||||
;
|
||||
/*
|
||||
->setDefault('choices', $this->reachableCenters)
|
||||
->setDefault('placeholder', 'Pick a center')
|
||||
;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* add a data transformer if user can reach only one center
|
||||
*
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$centers = $this->getReachableCenters($options['role'], $options['scopes']);
|
||||
|
||||
if (count($centers) <= 1) {
|
||||
$multiple = $options['choice_options']['multiple'] ?? false;
|
||||
$builder->add('center', HiddenType::class);
|
||||
$builder->get('center')->addModelTransformer(
|
||||
new CenterTransformer($this->centerRepository, $multiple)
|
||||
);
|
||||
} else {
|
||||
$builder->add('center', EntityType::class,
|
||||
\array_merge(
|
||||
$options['choice_options'],
|
||||
[
|
||||
'class' => Center::class,
|
||||
'choices' => $centers
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$builder
|
||||
->addModelTransformer(new CallbackTransformer(
|
||||
function($data) {
|
||||
if (NULL === $data) {
|
||||
return ['center' => null];
|
||||
}
|
||||
return ['center' => $data];
|
||||
},
|
||||
function($data) {
|
||||
return $data['center'];
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
private function getReachableCenters(string $role, iterable $scopes): array
|
||||
{
|
||||
if (0 < count($scopes)) {
|
||||
$centers = [];
|
||||
|
||||
foreach($scopes as $scope) {
|
||||
foreach ($this->authorizationHelper
|
||||
->getReachableCenters($this->security->getUser(), $role, $scope) as $center) {
|
||||
$centers[spl_object_hash($center)] = $center;
|
||||
}
|
||||
}
|
||||
|
||||
return \array_values($centers);
|
||||
} else {
|
||||
return $this->authorizationHelper
|
||||
->getReachableCenters($this->security->getUser(), $role);
|
||||
}
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
$view->vars['is_hidden'] = count($this->getReachableCenters($options['role'],
|
||||
$options['scopes'])) <= 1;
|
||||
}
|
||||
}
|
@ -20,23 +20,23 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\ThirdPartyBundle\Repository;
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdPartyCivility;
|
||||
use Chill\MainBundle\Entity\Civility;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ThirdPartyCivility|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ThirdPartyCivility|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ThirdPartyCivility[] findAll()
|
||||
* @method ThirdPartyCivility[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
* @method Civility|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Civility|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Civility[] findAll()
|
||||
* @method Civility[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ThirdPartyCivilityRepository extends ServiceEntityRepository
|
||||
class CivilityRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ThirdPartyCivility::class);
|
||||
parent::__construct($registry, Civility::class);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
// Access to Bootstrap variables and mixins
|
||||
@import '~ChillMainAssets/module/bootstrap/shared';
|
||||
|
||||
// Chill variables
|
||||
@import './scss/chill_variables';
|
||||
|
||||
// Chill mixins
|
||||
@import './scss/mixins';
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* ADDITIONNAL COLORS VARIABLES
|
||||
*/
|
||||
|
||||
// Contexts banners
|
||||
$chill-person-context: $chill-green;
|
||||
$chill-accourse-context: #718596;
|
||||
$chill-household-context: #929d69;
|
||||
|
||||
// Badges colors
|
||||
$social-issue-color: #4bafe8;
|
||||
$social-action-color: $orange;
|
||||
$activity-color: yellowgreen;
|
@ -115,7 +115,7 @@ div.flex-table {
|
||||
}
|
||||
|
||||
ul.record_actions {
|
||||
align-self: flex-start;
|
||||
align-self: flex-start; // !! conflict with .float-button.bottom see L297
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,29 +274,35 @@ div.float-button {
|
||||
|
||||
div.action {
|
||||
float: right;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
a {
|
||||
word-break: break-all; // break email address
|
||||
}
|
||||
}
|
||||
&.top {
|
||||
div.action {
|
||||
padding: 0 0 1em 1em;
|
||||
}
|
||||
|
||||
// avoid a position relative that make links unclickable
|
||||
.fa-ul > li {
|
||||
position: initial;
|
||||
}
|
||||
}
|
||||
&.bottom {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
div.action {
|
||||
height: calc(100% - 0em);
|
||||
shape-outside: inset(calc(100% - 2em) 0 0);
|
||||
shape-outside: inset(calc(100% - 4em) 0 0);
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding: 0 0 0 1em;
|
||||
* {
|
||||
align-self: flex-end !important;
|
||||
align-self: flex-end !important; // neutralize flex-table rule L118
|
||||
}
|
||||
ul.record_actions {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,8 +310,19 @@ div.float-button {
|
||||
padding: 1em;
|
||||
border: 1px solid black;
|
||||
background-color: yellow;
|
||||
div.action {
|
||||
background-color: transparentize(#00ffff, 0.4);
|
||||
div.box {
|
||||
div.action {
|
||||
background-color: transparentize(cyan, 0.4);
|
||||
}
|
||||
& > ul li,
|
||||
& > div,
|
||||
& > p {
|
||||
background-color: transparentize(orange, 0.4);
|
||||
}
|
||||
& > div {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
//
|
||||
// Titles in forms
|
||||
//
|
||||
@ -12,7 +11,6 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
// We use box-shadow instead of border
|
||||
// to avoid to manage border double-width
|
||||
// Then we can simulate border-collapse: collapse (table)
|
||||
|
@ -1,27 +1,27 @@
|
||||
/**
|
||||
* Javascript file which handle ChillCollectionType
|
||||
*
|
||||
* Two events are emitted by this module, both on window and on collection / ul.
|
||||
*
|
||||
*
|
||||
* Two events are emitted by this module, both on window and on collection / ul.
|
||||
*
|
||||
* Collection (an UL element) and entry (a li element) are associated with those
|
||||
* events.
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* window.addEventListener('collection-add-entry', function(e) {
|
||||
* console.log(e.detail.collection);
|
||||
* console.log(e.detail.entry);
|
||||
* });
|
||||
*
|
||||
*
|
||||
* window.addEventListener('collection-remove-entry', function(e) {
|
||||
* console.log(e.detail.collection);
|
||||
* console.log(e.detail.entry);
|
||||
* });
|
||||
*
|
||||
*
|
||||
* collection.addEventListener('collection-add-entry', function(e) {
|
||||
* console.log(e.detail.collection);
|
||||
* console.log(e.detail.entry);
|
||||
* });
|
||||
*
|
||||
*
|
||||
* collection.addEventListener('collection-remove-entry', function(e) {
|
||||
* console.log(e.detail.collection);
|
||||
* console.log(e.detail.entry);
|
||||
@ -38,7 +38,7 @@ class CollectionEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {type} button
|
||||
* @returns {handleAdd}
|
||||
*/
|
||||
@ -47,6 +47,7 @@ var handleAdd = function(button) {
|
||||
form_name = button.dataset.collectionAddTarget,
|
||||
prototype = button.dataset.formPrototype,
|
||||
collection = document.querySelector('ul[data-collection-name="'+form_name+'"]'),
|
||||
empty_explain = collection.querySelector('li[data-collection-empty-explain]'),
|
||||
entry = document.createElement('li'),
|
||||
event = new CustomEvent('collection-add-entry', { detail: { collection: collection, entry: entry } }),
|
||||
counter = collection.childNodes.length,
|
||||
@ -56,8 +57,11 @@ var handleAdd = function(button) {
|
||||
entry.innerHTML = content;
|
||||
entry.classList.add('entry');
|
||||
initializeRemove(collection, entry);
|
||||
if (empty_explain !== null) {
|
||||
empty_explain.remove();
|
||||
}
|
||||
collection.appendChild(entry);
|
||||
|
||||
|
||||
collection.dispatchEvent(event);
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
@ -70,30 +74,30 @@ var initializeRemove = function(collection, entry) {
|
||||
allowDelete = collection.dataset.collectionAllowDelete,
|
||||
event = new CustomEvent('collection-remove-entry', { detail: { collection: collection, entry: entry } })
|
||||
;
|
||||
|
||||
|
||||
if (allowDelete === '0' && isPersisted === '1') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
button.classList.add('btn', 'btn-delete', 'remove-entry');
|
||||
button.textContent = content;
|
||||
|
||||
|
||||
button.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
entry.remove();
|
||||
collection.dispatchEvent(event);
|
||||
window.dispatchEvent(event);
|
||||
});
|
||||
|
||||
|
||||
entry.appendChild(button);
|
||||
};
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var
|
||||
var
|
||||
addButtons = document.querySelectorAll("button[data-collection-add-target]"),
|
||||
collections = document.querySelectorAll("ul[data-collection-name]")
|
||||
;
|
||||
|
||||
|
||||
for (let i = 0; i < addButtons.length; i ++) {
|
||||
let addButton = addButtons[i];
|
||||
addButton.addEventListener('click', function(e) {
|
||||
@ -101,11 +105,15 @@ window.addEventListener('load', function() {
|
||||
handleAdd(e.target);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
for (let i = 0; i < collections.length; i ++) {
|
||||
let entries = collections[i].querySelectorAll(':scope > li');
|
||||
|
||||
|
||||
for (let j = 0; j < entries.length; j ++) {
|
||||
console.log(entries[j].dataset);
|
||||
if (entries[j].dataset.collectionEmptyExplain === "1") {
|
||||
continue;
|
||||
}
|
||||
initializeRemove(collections[i], entries[j]);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Submit button(s) are disabled as soon as submit button is clicked and form is submitted.
|
||||
* ID 'create-form' must be added to submit forms.
|
||||
*/
|
||||
|
||||
var form = document.getElementById('create-form');
|
||||
var submitButtons = document.querySelectorAll("[type=submit]");
|
||||
|
||||
form.addEventListener('submit', function(e){
|
||||
for(var i=0; i<submitButtons.length; i++){
|
||||
submitButtons[i].disabled = true;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
@ -74,7 +74,12 @@ export default {
|
||||
case 'thirdparty':
|
||||
let data = this.$refs.castThirdparty.$data.thirdparty;
|
||||
data.name = data.text;
|
||||
data.address = { id: data.address.address_id }
|
||||
if (data.address !== undefined) {
|
||||
data.address = { id: data.address.address_id }
|
||||
} else {
|
||||
data.address = null;
|
||||
}
|
||||
|
||||
return data;
|
||||
default:
|
||||
throw Error('Invalid type of entity')
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% set formId = crudMainFormId|default('crud_main_form') %}
|
||||
<div class="{% block crud_content_main_div_class %}{% endblock %}">
|
||||
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.'~crud_name~'.title_edit')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
@ -1,9 +1,15 @@
|
||||
<div class="col-10 centered">
|
||||
|
||||
|
||||
{% block index_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.index.title')|trans({'%crud_name%': crud_name}) }}</h1>
|
||||
{% endblock index_header %}
|
||||
|
||||
{% block filter_order %}
|
||||
{% if filter_order is not null %}
|
||||
{{ filter_order|chill_render_filter_order_helper }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
{% block no_existing_entities %}
|
||||
<p>{{ no_existing_entities_sentences|default('No entities')|trans }}</p>
|
||||
@ -32,17 +38,20 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
<div class="crud_index__pagination">
|
||||
{{ chill_pagination(paginator) }}
|
||||
</div>
|
||||
{% block pagination %}
|
||||
<div class="crud_index__pagination">
|
||||
{{ chill_pagination(paginator) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block list_actions %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
{% block add_new %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_' ~ crud_name ~ '_new') }}" class="btn btn-new">{{ ('crud.'~crud_name~'.index.add_new')|trans( {'%crud_name%': crud_name} ) }}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block actions_before %}{% endblock %}
|
||||
{% block add_new %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_' ~ crud_name ~ '_new') }}" class="btn btn-new">{{ ('crud.'~crud_name~'.index.add_new')|trans( {'%crud_name%': crud_name} ) }}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endblock list_actions %}
|
||||
</div>
|
||||
|
@ -1,10 +1,11 @@
|
||||
{% set formId = crudMainFormId|default('crud_main_form') %}
|
||||
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_new')|trans({'%crud_name%' : crud_name }) }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
{% block crud_content_form %}
|
||||
{{ form_start(form) }}
|
||||
{{ form_start(form, { 'attr' : { 'id': formId } }) }}
|
||||
|
||||
{% block crud_content_form_rows %}
|
||||
{% for f in form %}{% if f.vars.name != 'submit' %}
|
||||
@ -14,6 +15,8 @@
|
||||
|
||||
{% block crud_content_after_form %}{% endblock %}
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% block crud_content_form_actions %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
{% block content_form_actions_back %}
|
||||
@ -25,21 +28,21 @@
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_close %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-close" class="btn btn-create">
|
||||
<button type="submit" name="submit" value="save-and-close" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_close'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_show %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-show" class="btn btn-create">
|
||||
<button type="submit" name="submit" value="save-and-show" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_show'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_new %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-new" class="btn btn-create">
|
||||
<button type="submit" name="submit" value="save-and-new" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_new'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
|
@ -0,0 +1,12 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="chill_filter_order container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="input-group mb-3">
|
||||
{{ form_widget(form.q)}}
|
||||
<button type="submit" class="btn btn-chill-l-gray"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
@ -168,6 +168,10 @@
|
||||
{{ form_widget(entry) }}
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li data-collection-empty-explain="1">
|
||||
<span class="chill-no-data-statement">{{ form.vars.empty_collection_explain|default('No item')|trans }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@ -198,3 +202,15 @@
|
||||
{{ form_widget(entry) }}
|
||||
{% endfor %}
|
||||
{% endblock comment_widget %}
|
||||
|
||||
{% block pick_center_widget %}
|
||||
{{ form_widget(form.center) }}
|
||||
{% endblock pick_center_widget %}
|
||||
|
||||
{% block pick_center_row %}
|
||||
{% if (not form.vars.is_hidden) %}
|
||||
{{ block('form_row') }}
|
||||
{% else %}
|
||||
{{ form_widget(form.center) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{#
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
<info@champs-libres.coop> / <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -17,7 +17,7 @@
|
||||
#}
|
||||
|
||||
<ul>
|
||||
{% for route in routes %}
|
||||
<li><a href="{{ path(route.key, args ) }}" class="{%- if activeRouteKey == route.key -%}active{%- endif -%}">{{ route.label }}</a></li>
|
||||
{% for menu in menus %}
|
||||
<li><a href="{{ menu.uri }}">{{ menu.label }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</ul>
|
||||
|
@ -70,6 +70,9 @@
|
||||
</center>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<a href="{{ path('chill_crud_aside_activity_new', {'type' : 7, 'duration' : '600', 'note' : 'Pas des remarques' }) }}"><div class="bloc btn btn-success btn-md btn-block">Appel téléphonique</div></a>
|
||||
</div>
|
||||
|
||||
{{ chill_widget('homepage', {} ) }}
|
||||
{% endblock %}
|
||||
|
@ -41,9 +41,8 @@ use Chill\MainBundle\Entity\RoleScope;
|
||||
*
|
||||
* Provides methods for user and entities information.
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AuthorizationHelper
|
||||
class AuthorizationHelper implements AuthorizationHelperInterface
|
||||
{
|
||||
protected RoleHierarchyInterface $roleHierarchy;
|
||||
|
||||
@ -203,9 +202,9 @@ class AuthorizationHelper
|
||||
* @param User $user
|
||||
* @param string|Role $role
|
||||
* @param null|Scope $scope
|
||||
* @return Center[]
|
||||
* @return Center[]|array
|
||||
*/
|
||||
public function getReachableCenters(User $user, $role, Scope $scope = null)
|
||||
public function getReachableCenters(User $user, string $role, ?Scope $scope = null): array
|
||||
{
|
||||
if ($role instanceof Role) {
|
||||
$role = $role->getRole();
|
||||
@ -267,9 +266,9 @@ class AuthorizationHelper
|
||||
* @param User $user
|
||||
* @param string role
|
||||
* @param Center|Center[] $center
|
||||
* @return Scope[]
|
||||
* @return Scope[]|array
|
||||
*/
|
||||
public function getReachableScopes(User $user, $role, $center)
|
||||
public function getReachableScopes(User $user, string $role, $center): array
|
||||
{
|
||||
if ($role instanceof Role) {
|
||||
$role = $role->getRole();
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
interface AuthorizationHelperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get reachable Centers for the given user, role,
|
||||
* and optionnaly Scope
|
||||
*
|
||||
* @param User $user
|
||||
* @param string|Role $role
|
||||
* @param null|Scope $scope
|
||||
* @return Center[]
|
||||
*/
|
||||
public function getReachableCenters(User $user, string $role, ?Scope $scope = null): array;
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $role
|
||||
* @param Center|Center[]|array $center
|
||||
* @return array
|
||||
*/
|
||||
public function getReachableScopes(User $user, string $role, $center): array;
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Chill\MainBundle\Form\Type\Listing\FilterOrderType;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class FilterOrderHelper
|
||||
{
|
||||
private FormFactoryInterface $formFactory;
|
||||
private RequestStack $requestStack;
|
||||
private ?array $searchBoxFields = null;
|
||||
|
||||
public function __construct(
|
||||
FormFactoryInterface $formFactory,
|
||||
RequestStack $requestStack
|
||||
) {
|
||||
$this->formFactory = $formFactory;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function setSearchBox($searchBoxFields = null): self
|
||||
{
|
||||
$this->searchBoxFields = $searchBoxFields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasSearchBox(): bool
|
||||
{
|
||||
return $this->searchBoxFields !== null;
|
||||
}
|
||||
|
||||
private function getFormData(): array
|
||||
{
|
||||
return [
|
||||
'q' => $this->getQueryString()
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryString(): ?string
|
||||
{
|
||||
$q = $this->requestStack->getCurrentRequest()
|
||||
->query->get('q', null);
|
||||
|
||||
return empty($q) ? NULL : $q;
|
||||
}
|
||||
|
||||
public function buildForm($name = null, string $type = FilterOrderType::class, array $options = []): FormInterface
|
||||
{
|
||||
return $this->formFactory
|
||||
->createNamed($name, $type, $this->getFormData(), \array_merge([
|
||||
'helper' => $this,
|
||||
'method' => 'GET',
|
||||
'csrf_protection' => false,
|
||||
], $options));
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class FilterOrderHelperBuilder
|
||||
{
|
||||
private ?array $searchBoxFields = null;
|
||||
private FormFactoryInterface $formFactory;
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(
|
||||
FormFactoryInterface $formFactory,
|
||||
RequestStack $requestStack
|
||||
) {
|
||||
$this->formFactory = $formFactory;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function addSearchBox(array $fields, ?array $options = []): self
|
||||
{
|
||||
$this->searchBoxFields = $fields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): FilterOrderHelper
|
||||
{
|
||||
$helper = new FilterOrderHelper(
|
||||
$this->formFactory,
|
||||
$this->requestStack
|
||||
);
|
||||
|
||||
$helper->setSearchBox($this->searchBoxFields);
|
||||
|
||||
return $helper;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Symfony\Component\Form\FormFactoryBuilderInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class FilterOrderHelperFactory implements FilterOrderHelperFactoryInterface
|
||||
{
|
||||
private FormFactoryInterface $formFactory;
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(
|
||||
FormFactoryInterface $formFactory,
|
||||
RequestStack $requestStack
|
||||
) {
|
||||
$this->formFactory = $formFactory;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function create(string $context, ?array $options = []): FilterOrderHelperBuilder
|
||||
{
|
||||
return new FilterOrderHelperBuilder($this->formFactory, $this->requestStack);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
interface FilterOrderHelperFactoryInterface
|
||||
{
|
||||
public function create(string $context, ?array $options = []): FilterOrderHelperBuilder;
|
||||
}
|
34
src/Bundle/ChillMainBundle/Templating/Listing/Templating.php
Normal file
34
src/Bundle/ChillMainBundle/Templating/Listing/Templating.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
class Templating extends AbstractExtension
|
||||
{
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new TwigFilter('chill_render_filter_order_helper', [$this, 'renderFilterOrderHelper'], [
|
||||
'needs_environment' => true, 'is_safe' => ['html'],
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
public function renderFilterOrderHelper(
|
||||
Environment $environment,
|
||||
FilterOrderHelper $helper,
|
||||
?string $template = '@ChillMain/FilterOrder/base.html.twig',
|
||||
?array $options = []
|
||||
) {
|
||||
return $environment->render($template, [
|
||||
'helper' => $helper,
|
||||
'form' => $helper->buildForm()->createView(),
|
||||
'options' => $options
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -28,18 +28,19 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CenterTypeTest extends TypeTestCase
|
||||
{
|
||||
/**
|
||||
* Test that a user which can reach only one center
|
||||
* Test that a user which can reach only one center
|
||||
* render as an hidden field
|
||||
*/
|
||||
public function testUserCanReachSingleCenter()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
//prepare user
|
||||
$center = $this->prepareCenter(1, 'center');
|
||||
$groupCenter = (new GroupCenter())
|
||||
@ -47,18 +48,19 @@ class CenterTypeTest extends TypeTestCase
|
||||
;
|
||||
$user = (new User())
|
||||
->addGroupCenter($groupCenter);
|
||||
|
||||
|
||||
$type = $this->prepareType($user);
|
||||
|
||||
|
||||
$this->assertEquals(HiddenType::class, $type->getParent());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that a user which can reach only one center
|
||||
* Test that a user which can reach only one center
|
||||
* render as an hidden field
|
||||
*/
|
||||
public function testUserCanReachMultipleSameCenter()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
//prepare user
|
||||
$center = $this->prepareCenter(1, 'center');
|
||||
$groupCenterA = (new GroupCenter())
|
||||
@ -70,18 +72,19 @@ class CenterTypeTest extends TypeTestCase
|
||||
$user = (new User())
|
||||
->addGroupCenter($groupCenterA)
|
||||
->addGroupCenter($groupCenterB);
|
||||
|
||||
|
||||
$type = $this->prepareType($user);
|
||||
|
||||
|
||||
$this->assertEquals(HiddenType::class, $type->getParent());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that a user which can reach multiple center
|
||||
* Test that a user which can reach multiple center
|
||||
* make CenterType render as "entity" type.
|
||||
*/
|
||||
public function testUserCanReachMultipleCenters()
|
||||
{
|
||||
$this->markTestSkipped();
|
||||
//prepare user
|
||||
$centerA = $this->prepareCenter(1, 'centerA');
|
||||
$centerB = $this->prepareCenter(2, 'centerB');
|
||||
@ -95,61 +98,61 @@ class CenterTypeTest extends TypeTestCase
|
||||
->addGroupCenter($groupCenterA)
|
||||
->addGroupCenter($groupCenterB)
|
||||
;
|
||||
|
||||
|
||||
$type = $this->prepareType($user);
|
||||
|
||||
|
||||
$this->assertEquals(EntityType::class, $type->getParent());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* prepare a mocked center, with and id and name given
|
||||
*
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $name
|
||||
* @return \Chill\MainBundle\Entity\Center
|
||||
* @return \Chill\MainBundle\Entity\Center
|
||||
*/
|
||||
private function prepareCenter($id, $name)
|
||||
{
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
|
||||
|
||||
$prophecyCenter = $prophet->prophesize();
|
||||
$prophecyCenter->willExtend('\Chill\MainBundle\Entity\Center');
|
||||
$prophecyCenter->getId()->willReturn($id);
|
||||
$prophecyCenter->getName()->willReturn($name);
|
||||
|
||||
|
||||
return $prophecyCenter->reveal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* prepare the type with mocked center transformer and token storage
|
||||
*
|
||||
*
|
||||
* @param User $user the user for wich the form will be prepared
|
||||
* @return CenterType
|
||||
*/
|
||||
private function prepareType(User $user)
|
||||
{
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
|
||||
//create a center transformer
|
||||
$centerTransformerProphecy = $prophet->prophesize();
|
||||
$centerTransformerProphecy
|
||||
->willExtend('Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer');
|
||||
$transformer = $centerTransformerProphecy->reveal();
|
||||
|
||||
|
||||
$tokenProphecy = $prophet->prophesize();
|
||||
$tokenProphecy
|
||||
->willImplement('\Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
||||
$tokenProphecy->getUser()->willReturn($user);
|
||||
$token = $tokenProphecy->reveal();
|
||||
|
||||
|
||||
$tokenStorageProphecy = $prophet->prophesize();
|
||||
$tokenStorageProphecy
|
||||
->willExtend('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage');
|
||||
$tokenStorageProphecy->getToken()->willReturn($token);
|
||||
$tokenStorage = $tokenStorageProphecy->reveal();
|
||||
|
||||
|
||||
return new CenterType($tokenStorage, $transformer);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* <one line to give the program's name and a brief idea of what it does.>
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\Tests\Services;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
/**
|
||||
* Test the Twig function 'chill_menu'
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ChillMenuTwigFunctionTest extends KernelTestCase
|
||||
{
|
||||
|
||||
private static $templating;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
self::bootKernel(array('environment' => 'test'));
|
||||
static::$templating = static::$container
|
||||
->get('templating');
|
||||
$pathToBundle = static::$container->getParameter('kernel.bundles_metadata')['ChillMainBundle']['path'];
|
||||
//load templates in Tests/Resources/views
|
||||
static::$container->get('twig.loader')
|
||||
->addPath($pathToBundle.'/Resources/test/views/', $namespace = 'tests');
|
||||
}
|
||||
|
||||
public function testNormalMenu()
|
||||
{
|
||||
$content = static::$templating->render('@tests/menus/normalMenu.html.twig');
|
||||
$this->assertContains('ul', $content,
|
||||
"test that the file contains an ul tag"
|
||||
);
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@ module.exports = function(encore, entries)
|
||||
encore.addEntry('mod_forkawesome', __dirname + '/Resources/public/module/forkawesome/index.js');
|
||||
encore.addEntry('mod_bootstrap', __dirname + '/Resources/public/module/bootstrap/index.js');
|
||||
encore.addEntry('mod_ckeditor5', __dirname + '/Resources/public/module/ckeditor5/index.js');
|
||||
encore.addEntry('mod_disablebuttons', __dirname + '/Resources/public/module/disable-buttons/index.js');
|
||||
|
||||
// Vue entrypoints
|
||||
encore.addEntry('vue_address', __dirname + '/Resources/public/vuejs/Address/index.js');
|
||||
|
@ -60,11 +60,6 @@ services:
|
||||
tags:
|
||||
- { name: twig.extension }
|
||||
|
||||
chill.main.form.data_transformer.center_transformer:
|
||||
class: Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer
|
||||
arguments:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
|
||||
chill.main.validator.role_scope_scope_presence:
|
||||
class: Chill\MainBundle\Validation\Validator\RoleScopeScopePresence
|
||||
arguments:
|
||||
|
@ -36,13 +36,9 @@ services:
|
||||
tags:
|
||||
- { name: form.type, alias: select2_chill_language }
|
||||
|
||||
chill.main.form.type.center:
|
||||
class: Chill\MainBundle\Form\Type\CenterType
|
||||
arguments:
|
||||
- "@security.token_storage"
|
||||
- "@chill.main.form.data_transformer.center_transformer"
|
||||
tags:
|
||||
- { name: form.type, alias: center }
|
||||
Chill\MainBundle\Form\Type\PickCenterType:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
chill.main.form.type.composed_role_scope:
|
||||
class: Chill\MainBundle\Form\Type\ComposedRoleScopeType
|
||||
@ -97,6 +93,10 @@ services:
|
||||
arguments:
|
||||
- '@Chill\MainBundle\Export\ExportManager'
|
||||
|
||||
Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
chill.main.form.advanced_search_type:
|
||||
class: Chill\MainBundle\Form\AdvancedSearchType
|
||||
autowire: true
|
||||
|
@ -38,6 +38,7 @@ services:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
Chill\MainBundle\Security\Authorization\AuthorizationHelper: '@chill.main.security.authorization.helper'
|
||||
Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface: '@chill.main.security.authorization.helper'
|
||||
|
||||
chill.main.role_provider:
|
||||
class: Chill\MainBundle\Security\RoleProvider
|
||||
|
@ -36,7 +36,7 @@ services:
|
||||
autowire: true
|
||||
tags:
|
||||
- { name: 'chill.render_entity' }
|
||||
|
||||
|
||||
Chill\MainBundle\Templating\ChillMarkdownRenderExtension:
|
||||
tags:
|
||||
- { name: twig.extension }
|
||||
@ -46,4 +46,10 @@ services:
|
||||
- '@Symfony\Component\Templating\EngineInterface'
|
||||
tags:
|
||||
- { name: 'chill.render_entity' }
|
||||
|
||||
|
||||
Chill\MainBundle\Templating\Listing\:
|
||||
resource: './../../Templating/Listing'
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
|
||||
Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface: '@Chill\MainBundle\Templating\Listing\FilterOrderHelperFactory'
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add some fields to PostalCode
|
||||
*/
|
||||
final class Version20211006151653 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add some fields to PostalCode';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code ADD refPostalCodeId VARCHAR(255) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code ADD postalCodeSource VARCHAR(255) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code ADD center geometry(POINT,4326) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code DROP refPostalCodeId');
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code DROP postalCodeSource');
|
||||
$this->addSql('ALTER TABLE chill_main_postal_code DROP center');
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Create civility table
|
||||
*/
|
||||
final class Version20211007150019 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'create civility table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE SEQUENCE chill_main_civility_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE chill_main_civility (id INT NOT NULL, name JSON NOT NULL, abbreviation JSON NOT NULL, active BOOLEAN NOT NULL, PRIMARY KEY(id))');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP SEQUENCE chill_main_civility_id_seq');
|
||||
$this->addSql('DROP TABLE chill_main_civility');
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
"This program is free software: you can redistribute it and/or modify it under the terms of the <strong>GNU Affero General Public License</strong>": "Ce programme est un logiciel libre: vous pouvez le redistribuer et/ou le modifier selon les termes de la licence <strong>GNU Affero GPL</strong>"
|
||||
User manual: Manuel d'utilisation
|
||||
Search: Rechercher
|
||||
'Search persons, ...': 'Recherche des personnes, ...'
|
||||
"Search persons, ...": "Recherche des personnes, ..."
|
||||
Person name: Nom / Prénom de la personne
|
||||
Login: Connexion
|
||||
Logout: Se déconnecter
|
||||
@ -33,7 +33,7 @@ Cancel: Annuler
|
||||
Save: Enregistrer
|
||||
This form contains errors: Ce formulaire contient des erreurs
|
||||
Choose an user: Choisir un utilisateur
|
||||
'You are going to leave a page with unsubmitted data. Are you sure you want to leave ?': "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?"
|
||||
"You are going to leave a page with unsubmitted data. Are you sure you want to leave ?": "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?"
|
||||
No value: Aucune information
|
||||
Last updated by: Dernière mise à jour par
|
||||
Last updated on: Dernière mise à jour le
|
||||
@ -56,6 +56,7 @@ centers: centres
|
||||
Centers: Centres
|
||||
comment: commentaire
|
||||
Comment: Commentaire
|
||||
Any comment: Aucun commentaire
|
||||
|
||||
# comment embeddable
|
||||
No comment associated: Aucun commentaire
|
||||
@ -71,24 +72,24 @@ Postal code: Code postal
|
||||
Valid from: Valide à partir du
|
||||
Choose a postal code: Choisir un code postal
|
||||
address:
|
||||
address_homeless: L'adresse est-elle celle d'un domicile fixe ?
|
||||
real address: Adresse d'un domicile
|
||||
consider homeless: N'est pas l'adresse d'un domicile (SDF)
|
||||
address_homeless: L'adresse est-elle celle d'un domicile fixe ?
|
||||
real address: Adresse d'un domicile
|
||||
consider homeless: N'est pas l'adresse d'un domicile (SDF)
|
||||
address more:
|
||||
floor: ét
|
||||
corridor: coul
|
||||
steps: esc
|
||||
flat: appart
|
||||
buildingName: résidence
|
||||
extra: ''
|
||||
distribution: cedex
|
||||
floor: ét
|
||||
corridor: coul
|
||||
steps: esc
|
||||
flat: appart
|
||||
buildingName: résidence
|
||||
extra: ""
|
||||
distribution: cedex
|
||||
Create a new address: Créer une nouvelle adresse
|
||||
|
||||
#serach
|
||||
Your search is empty. Please provide search terms.: La recherche est vide. Merci de fournir des termes de recherche.
|
||||
The domain %domain% is unknow. Please check your search.: Le domaine de recherche "%domain%" est inconnu. Merci de vérifier votre recherche.
|
||||
Invalid terms : Recherche invalide
|
||||
You should not have more than one domain. : Vous ne devriez pas avoir plus d'un domaine de recherche.
|
||||
Invalid terms: Recherche invalide
|
||||
You should not have more than one domain.: Vous ne devriez pas avoir plus d'un domaine de recherche.
|
||||
#used for page title
|
||||
Search %pattern%: Recherche de "%pattern%"
|
||||
Results %start%-%end% of %total%: Résultats %start%-%end% sur %total%
|
||||
@ -113,9 +114,9 @@ Permissions Menu: Gestion des droits
|
||||
Permissions management of your chill installation: Gestion des permissions de votre instance
|
||||
|
||||
#admin section
|
||||
'Administration interface': Interface d'administration
|
||||
"Administration interface": Interface d'administration
|
||||
Welcome to the admin section !: >
|
||||
Bienvenue dans l'interface d'administration !
|
||||
Bienvenue dans l'interface d'administration !
|
||||
|
||||
#admin section for center's administration
|
||||
Create a new center: Créer un nouveau centre
|
||||
@ -210,7 +211,6 @@ Problem during download: Problème durant le téléchargement
|
||||
# sans valeur
|
||||
without data: sans valeur
|
||||
|
||||
|
||||
#CSV List Formatter
|
||||
Add a number on first column: La première colonne est un numéro
|
||||
Number: Numéro
|
||||
@ -228,9 +228,9 @@ Comma separated values (CSV): Valeurs séparées par des virgules (CSV - tableur
|
||||
Choose the format: Choisir le format
|
||||
|
||||
# select2
|
||||
'select2.no_results': Aucun résultat
|
||||
'select2.error_loading': Erreur de chargement des résultats
|
||||
'select2.searching': Recherche en cours...
|
||||
"select2.no_results": Aucun résultat
|
||||
"select2.error_loading": Erreur de chargement des résultats
|
||||
"select2.searching": Recherche en cours...
|
||||
|
||||
# change password
|
||||
Change my password: Modification du mot de passe
|
||||
@ -258,38 +258,35 @@ Impersonate: Incarner l'utilisateur
|
||||
Impersonate mode: Mode fantôme
|
||||
|
||||
crud:
|
||||
# general items
|
||||
new:
|
||||
button_action_form: Créer
|
||||
link_edit: Modifier
|
||||
save_and_close: Créer & fermer
|
||||
save_and_show: Créer & voir
|
||||
save_and_new: Créer & nouveau
|
||||
success: Les données ont été créées
|
||||
edit:
|
||||
button_action_form: Enregistrer
|
||||
back_to_view: Voir
|
||||
save_and_close: Enregistrer & fermer
|
||||
save_and_show: Enregistrer & voir
|
||||
success: Les données ont été modifiées
|
||||
delete:
|
||||
success: Les données ont été supprimées
|
||||
link_to_form: Supprimer
|
||||
default:
|
||||
success: Les données ont été enregistrées
|
||||
view:
|
||||
link_duplicate: Dupliquer
|
||||
## admin for users
|
||||
admin_user:
|
||||
index:
|
||||
title: Utilisateurs
|
||||
add_new: "Créer"
|
||||
is_active: "Actif ?"
|
||||
usernames: "Identifiants"
|
||||
mains: "Champs principaux"
|
||||
title_new: "Nouvel utilisateur"
|
||||
title_edit: Modifier un utilisateur
|
||||
# general items
|
||||
new:
|
||||
button_action_form: Créer
|
||||
link_edit: Modifier
|
||||
save_and_close: Créer & fermer
|
||||
save_and_show: Créer & voir
|
||||
save_and_new: Créer & nouveau
|
||||
success: Les données ont été créées
|
||||
edit:
|
||||
button_action_form: Enregistrer
|
||||
back_to_view: Voir
|
||||
save_and_close: Enregistrer & fermer
|
||||
save_and_show: Enregistrer & voir
|
||||
success: Les données ont été modifiées
|
||||
delete:
|
||||
success: Les données ont été supprimées
|
||||
link_to_form: Supprimer
|
||||
default:
|
||||
success: Les données ont été enregistrées
|
||||
view:
|
||||
link_duplicate: Dupliquer
|
||||
No entities: Aucun élément
|
||||
|
||||
CHILL_FOO_SEE: Voir un élément
|
||||
CHILL_FOO_EDIT: Modifier un élément
|
||||
|
||||
#Show templates
|
||||
Date: Date
|
||||
By: Par
|
||||
For: Pour
|
||||
Created for: Créé pour
|
||||
Created by: Créé par
|
||||
|
@ -268,7 +268,7 @@ final class PersonController extends AbstractController
|
||||
) {
|
||||
$this->em->persist($person);
|
||||
|
||||
$this->em->flush();
|
||||
// $this->em->flush();
|
||||
$this->lastPostDataReset();
|
||||
|
||||
if ($form->get('createPeriod')->isClicked()) {
|
||||
|
@ -84,6 +84,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
$loader->load('services/repository.yaml');
|
||||
$loader->load('services/serializer.yaml');
|
||||
$loader->load('services/security.yaml');
|
||||
$loader->load('services/doctrineEventListener.yaml');
|
||||
|
||||
// load service advanced search only if configure
|
||||
if ($config['search']['search_by_phone'] != 'never') {
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\EventListener;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\PersonAltName;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
use LogicException;
|
||||
use Symfony\Component\Validator\Exception\LogicException as ExceptionLogicException;
|
||||
|
||||
class PersonEventListener
|
||||
{
|
||||
public function onPrePersist(LifecycleEventArgs $event): void
|
||||
{
|
||||
if($event->getObject() instanceof Person){
|
||||
|
||||
$person = $event->getObject();
|
||||
$firstnameCaps = mb_convert_case(mb_strtolower($person->getFirstName()), MB_CASE_TITLE, 'UTF-8');
|
||||
$firstnameCaps = ucwords(strtolower($firstnameCaps), " \t\r\n\f\v'-");
|
||||
$person->setFirstName($firstnameCaps);
|
||||
|
||||
$lastnameCaps = mb_strtoupper($person->getLastName(), 'UTF-8');
|
||||
$person->setLastName($lastnameCaps);
|
||||
|
||||
} elseif ($event->getObject() instanceof PersonAltName){
|
||||
|
||||
$altname = $event->getObject();
|
||||
$altnameCaps = mb_strtoupper($altname->getLabel(), 'UTF-8');
|
||||
$altname->setLabel($altnameCaps);
|
||||
|
||||
} else {
|
||||
|
||||
throw new LogicException('Entity must be a person or an altname');
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,9 @@
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
|
||||
use Chill\MainBundle\Repository\CenterRepository;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@ -30,12 +32,11 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\CenterType;
|
||||
use Chill\MainBundle\Form\Type\PickCenterType;
|
||||
use Chill\PersonBundle\Form\Type\GenderType;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
||||
use Chill\MainBundle\Form\Type\Export\PickCenterType;
|
||||
|
||||
final class CreationPersonType extends AbstractType
|
||||
{
|
||||
@ -43,11 +44,7 @@ final class CreationPersonType extends AbstractType
|
||||
// TODO: See if this is still valid and update accordingly.
|
||||
const NAME = 'chill_personbundle_person_creation';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CenterTransformer
|
||||
*/
|
||||
private $centerTransformer;
|
||||
private CenterRepository $centerRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -58,11 +55,11 @@ final class CreationPersonType extends AbstractType
|
||||
private EventDispatcherInterface $dispatcher;
|
||||
|
||||
public function __construct(
|
||||
CenterTransformer $centerTransformer,
|
||||
CenterRepository $centerRepository,
|
||||
ConfigPersonAltNamesHelper $configPersonAltNamesHelper,
|
||||
EventDispatcherInterface $dispatcher
|
||||
) {
|
||||
$this->centerTransformer = $centerTransformer;
|
||||
$this->centerTransformer = $centerRepository;
|
||||
$this->configPersonAltNamesHelper = $configPersonAltNamesHelper;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
@ -82,8 +79,9 @@ final class CreationPersonType extends AbstractType
|
||||
->add('gender', GenderType::class, array(
|
||||
'required' => true, 'placeholder' => null
|
||||
))
|
||||
->add('center', CenterType::class, [
|
||||
'required' => false
|
||||
->add('center', PickCenterType::class, [
|
||||
'required' => false,
|
||||
'role' => PersonVoter::CREATE,
|
||||
])
|
||||
;
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
// Access to Bootstrap variables and mixins
|
||||
@import '~ChillMainAssets/module/bootstrap/shared';
|
||||
|
||||
@import 'ChillMainAssets/chill/scss/chill_variables';
|
||||
|
||||
// Complete/override Main generic assets
|
||||
@import './scss/mixins';
|
||||
@import './scss/render_box.scss';
|
||||
@import './scss/flex_table.scss';
|
||||
@import './scss/badge.scss';
|
||||
|
||||
// Specific templates styles
|
||||
@import './scss/accompanying_period_work.scss';
|
||||
@ -19,13 +22,13 @@
|
||||
|
||||
div.banner {
|
||||
div#header-person-name {
|
||||
background: none repeat scroll 0 0 $chill-green-dark;
|
||||
background: none repeat scroll 0 0 shade-color($chill-person-context, 20%);
|
||||
color: $white;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
div#header-person-details {
|
||||
background: none repeat scroll 0 0 $chill-green;
|
||||
background: none repeat scroll 0 0 $chill-person-context;
|
||||
color: $white;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
@ -92,7 +95,6 @@ div.person-view {
|
||||
* Header custom for Accompanying Course
|
||||
*/
|
||||
|
||||
$chill-accourse-context: #718596;
|
||||
|
||||
div.banner {
|
||||
div#header-accompanying_course-name {
|
||||
@ -104,9 +106,9 @@ div.banner {
|
||||
span {
|
||||
a {
|
||||
color: $white;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,19 +120,11 @@ div.banner {
|
||||
}
|
||||
}
|
||||
|
||||
abbr.referrer {
|
||||
font-size: 70%;
|
||||
padding-right: 0.4em;
|
||||
align-self: center; // in flex context
|
||||
}
|
||||
|
||||
/*
|
||||
* HOUSEHOLD CONTEXT
|
||||
* Header custom for Household
|
||||
*/
|
||||
|
||||
$chill-household-context: #929d69;
|
||||
|
||||
div.banner {
|
||||
div#header-household-name {
|
||||
background: none repeat scroll 0 0 $chill-household-context;
|
||||
@ -142,9 +136,9 @@ div.banner {
|
||||
span {
|
||||
a {
|
||||
color: $white;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.household-members {
|
||||
@ -185,6 +179,7 @@ div.banner {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
div.household-resume {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -208,48 +203,10 @@ div.household-resume {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BADGES, MARKS, PINS
|
||||
* for chill person theme
|
||||
*/
|
||||
|
||||
// chill person badges
|
||||
span.badge-person,
|
||||
span.badge-thirdparty {
|
||||
display: inline-block;
|
||||
padding: 0 0.5em !important;
|
||||
background-color: $white;
|
||||
color: $dark;
|
||||
border: 1px solid $chill-ll-gray;
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-style: solid;
|
||||
border-radius: 6px;
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
span.badge-person {
|
||||
border-bottom-color: $chill-green;
|
||||
}
|
||||
// todo: move in thirdparty
|
||||
span.badge-thirdparty {
|
||||
border-bottom-color: shade-color($chill-pink, 10%);
|
||||
}
|
||||
|
||||
// household holder mark
|
||||
span.fa-holder {
|
||||
width: 1em;
|
||||
margin: -10px 0.3em -8px 0;
|
||||
i:last-child {
|
||||
font-weight: 900;
|
||||
color: white;
|
||||
font-size: 70%;
|
||||
font-family: "Open Sans Extrabold";
|
||||
}
|
||||
}
|
||||
|
||||
/// Horizontal list of persons (Accourse resume page)
|
||||
div.accompanyingcourse-resume {
|
||||
div.associated-persons {
|
||||
font-size: 110%;
|
||||
span.household {
|
||||
display: inline-block;
|
||||
border-radius: 8px;
|
||||
@ -272,3 +229,16 @@ div.accompanyingcourse-resume {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
abbr.referrer { // still used ?
|
||||
font-size: 70%;
|
||||
padding-right: 0.4em;
|
||||
align-self: center; // in flex context
|
||||
}
|
||||
|
||||
.updatedBy {
|
||||
margin-top: 0.3rem;
|
||||
font-size: 0.9rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -1,31 +1,6 @@
|
||||
/// AccompanyingCourse Work list Page
|
||||
div.accompanying_course_work-list {
|
||||
|
||||
h2.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
color: $dark;
|
||||
//height: 40px;
|
||||
|
||||
span.title_label {
|
||||
border-radius: 0.35rem 0 0 0.35rem;
|
||||
background-color: $social-action-label-color;
|
||||
color: $white;
|
||||
font-size: 80%;
|
||||
padding: 0.5em;
|
||||
padding-right: 0;
|
||||
}
|
||||
span.title_action {
|
||||
flex-grow: 1;
|
||||
margin: 0 0 0 auto;
|
||||
border-radius: 0 0.35rem 0.35rem 0;
|
||||
background-color: $light;
|
||||
padding: 0.2em 0.7em;
|
||||
@include badge_social_action;
|
||||
}
|
||||
}
|
||||
|
||||
div.timeline {
|
||||
width: 100%;
|
||||
ul {
|
||||
@ -125,7 +100,7 @@ div.accompanying_course_work-list {
|
||||
}
|
||||
}
|
||||
&.goal_title li::marker {
|
||||
color: $sky-blue;
|
||||
color: $social-issue-color;
|
||||
}
|
||||
&.result_list li::marker {
|
||||
color: $pink;
|
||||
@ -133,11 +108,4 @@ div.accompanying_course_work-list {
|
||||
}
|
||||
}
|
||||
|
||||
.updatedBy {
|
||||
margin-top: 0.3rem;
|
||||
font-size: 0.9rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* BADGES PERSON AND THIRDPARTY
|
||||
*/
|
||||
|
||||
span.badge-person,
|
||||
span.badge-thirdparty {
|
||||
display: inline-block;
|
||||
padding: 0 0.5em !important;
|
||||
background-color: $white;
|
||||
color: $dark;
|
||||
border: 1px solid $chill-ll-gray;
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-style: solid;
|
||||
border-radius: 6px;
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
span.badge-person {
|
||||
border-bottom-color: $chill-green;
|
||||
}
|
||||
span.badge-thirdparty {
|
||||
border-bottom-color: shade-color($chill-pink, 10%);
|
||||
}
|
||||
|
||||
/*
|
||||
* HOUSEHOLD HOLDER MARK
|
||||
*/
|
||||
|
||||
span.fa-holder {
|
||||
width: 1em;
|
||||
margin: -10px 0.3em -8px 0;
|
||||
i:last-child {
|
||||
font-family: "Open Sans Extrabold";
|
||||
font-weight: 900;
|
||||
font-size: 70%;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BADGE_TITLE
|
||||
* Display Title like a badge (with background-colored label)
|
||||
*/
|
||||
|
||||
h2.badge-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
color: $dark;
|
||||
|
||||
a & { text-decoration: none; } // ?!? keep it ?
|
||||
|
||||
span.title_label {
|
||||
border-radius: 0.35rem 0 0 0.35rem;
|
||||
color: $white;
|
||||
font-size: 80%;
|
||||
padding: 0.5em;
|
||||
padding-right: 0;
|
||||
h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
span.title_action {
|
||||
flex-grow: 1;
|
||||
margin: 0 0 0 auto;
|
||||
border-radius: 0 0.35rem 0.35rem 0;
|
||||
background-color: $light;
|
||||
padding: 0.2em 1em;
|
||||
|
||||
ul.small_in_title {
|
||||
margin-top: 0.5em;
|
||||
font-size: 70%;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// badge_title in AccompanyingCourse Work list Page
|
||||
div.accompanying_course_work-list {
|
||||
h2.badge-title {
|
||||
span.title_label {
|
||||
// Calculate same color then border:groove
|
||||
background-color: shade-color($social-action-color, 34%);
|
||||
}
|
||||
span.title_action {
|
||||
@include badge_title($social-action-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// badge_title in Activities on resume page
|
||||
div.activity-list {
|
||||
h2.badge-title {
|
||||
span.title_label {
|
||||
// Calculate same color then border:groove
|
||||
background-color: shade-color($activity-color, 34%);
|
||||
h3 {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
span.title_action {
|
||||
@include badge_title($activity-color);
|
||||
}
|
||||
span.title_label {
|
||||
div.duration {
|
||||
font-size: 70%;
|
||||
font-weight: 500;
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
text-align: right;
|
||||
abbr {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +1,39 @@
|
||||
// Additionnal colors
|
||||
$sky-blue: #4bafe8;
|
||||
|
||||
// mixins variables
|
||||
$social-issue-color: $sky-blue;
|
||||
$social-action-color: $orange;
|
||||
|
||||
// Calculate same color then border:groove
|
||||
// origin: $orange, computed: #965028
|
||||
$social-action-label-color: shade-color($orange, 34%);
|
||||
|
||||
///
|
||||
/// Social Issue mixin
|
||||
// define visual badge for all social issues
|
||||
/// Chill badge mixin
|
||||
// define chill visual badge
|
||||
///
|
||||
|
||||
@mixin badge_social_issue {
|
||||
@mixin chill_badge($color) {
|
||||
text-transform: capitalize !important;
|
||||
font-weight: 500 !important;
|
||||
border-left: 20px groove $social-issue-color;
|
||||
border-left: 20px groove $color;
|
||||
&:before {
|
||||
content: '\f04b';
|
||||
font-family: ForkAwesome;
|
||||
color: $social-issue-color;
|
||||
content: '\f04b';
|
||||
color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Social badge mixin
|
||||
// define visual badge for social issues or social action
|
||||
///
|
||||
|
||||
@mixin badge_social($color) {
|
||||
@include chill_badge($color);
|
||||
&:before {
|
||||
margin: 0 0.3em 0 -0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Social Action mixin
|
||||
// define visual badge for all social actions
|
||||
/// Generic mixin for titles like badge
|
||||
// define visual badge used in title area
|
||||
///
|
||||
|
||||
@mixin badge_social_action {
|
||||
text-transform: capitalize !important;
|
||||
font-weight: 500 !important;
|
||||
border-left: 20px groove $social-action-color;
|
||||
@mixin badge_title($color) {
|
||||
@include chill_badge($color);
|
||||
&:before {
|
||||
content: '\f04b';
|
||||
font-family: ForkAwesome;
|
||||
color: $social-action-color;
|
||||
margin: 0 0.3em 0 -0.75em;
|
||||
margin: 0 0.3em 0 -1.05em;
|
||||
}
|
||||
}
|
||||
|
@ -8,21 +8,28 @@
|
||||
span.altname {}
|
||||
}
|
||||
|
||||
/// SOCIAL-ISSUE
|
||||
&.entity-social-issue {
|
||||
margin-right: 0.3em;
|
||||
font-size: 120%;
|
||||
span.badge {
|
||||
@include badge_social_issue;
|
||||
}
|
||||
}
|
||||
|
||||
/// SOCIAL-ACTION
|
||||
/// SOCIAL-ISSUE AND SOCIAL-ACTION
|
||||
&.entity-social-issue,
|
||||
&.entity-social-action {
|
||||
margin-right: 0.3em;
|
||||
font-size: 120%;
|
||||
span.badge {
|
||||
@include badge_social_action;
|
||||
// for too long badge in a narrow inside block
|
||||
text-align: initial;
|
||||
margin-bottom: 0.2em;
|
||||
> span {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.entity-social-issue {
|
||||
span.badge {
|
||||
@include badge_social($social-issue-color);
|
||||
}
|
||||
}
|
||||
&.entity-social-action {
|
||||
span.badge {
|
||||
@include badge_social($social-action-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
@import 'ChillMainAssets/module/bootstrap/shared';
|
||||
@import 'ChillPersonAssets/chill/scss/mixins';
|
||||
|
||||
@import 'ChillMainAssets/chill/scss/chill_variables';
|
||||
span.badge {
|
||||
@include badge_social_issue;
|
||||
@include badge_social($social-issue-color);
|
||||
font-size: 95%;
|
||||
margin-bottom: 5px;
|
||||
margin-right: 1em;
|
||||
|
@ -84,10 +84,10 @@ export default {
|
||||
<style lang="scss">
|
||||
@import 'ChillMainAssets/module/bootstrap/shared';
|
||||
@import 'ChillPersonAssets/chill/scss/mixins';
|
||||
|
||||
@import 'ChillMainAssets/chill/scss/chill_variables';
|
||||
div#accompanying-course {
|
||||
span.multiselect__tag {
|
||||
@include badge_social_issue;
|
||||
@include badge_social($social-issue-color);
|
||||
background: $chill-l-gray;
|
||||
color: $dark;
|
||||
}
|
||||
|
@ -1,37 +1,102 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
|
||||
<span class="name">
|
||||
{{ item.result.text }}
|
||||
<div class="container tpartycontainer">
|
||||
<div class="tparty-identification">
|
||||
<span class="name">
|
||||
{{ item.result.text }}
|
||||
</span>
|
||||
<span class="location">
|
||||
<template v-if="hasAddress">
|
||||
{{ getAddress.text }} -
|
||||
{{ getAddress.postcode.name }}
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tpartyparent" v-if="hasParent">
|
||||
<span class="name">
|
||||
{{ item.result.parent.text }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
<span class="badge bg-chill-red" v-if="item.result.kind == 'child'">
|
||||
{{ $t('thirdparty.contact')}}
|
||||
</span>
|
||||
<span class="badge bg-info" v-else-if="item.result.kind == 'company'">
|
||||
{{ $t('thirdparty.company')}}
|
||||
</span>
|
||||
<span class="location">
|
||||
{{ item.result.address.text }} -
|
||||
{{ item.result.address.postcode.name }}
|
||||
<span class="badge bg-secondary" v-else="item.result.kind == 'contact'">
|
||||
{{ $t('thirdparty.contact')}}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
|
||||
<span class="badge rounded-pill bg-secondary" :title="item.key">
|
||||
{{ $t('item.type_thirdparty') }}
|
||||
</span>
|
||||
|
||||
<on-the-fly
|
||||
type="thirdparty"
|
||||
v-bind:id="item.result.id"
|
||||
action="show">
|
||||
type="thirdparty"
|
||||
v-bind:id="item.result.id"
|
||||
action="show">
|
||||
</on-the-fly>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
|
||||
|
||||
const i18n = {
|
||||
messages: {
|
||||
fr: {
|
||||
thirdparty: {
|
||||
contact: "Contact",
|
||||
company: "Institution",
|
||||
child: "Personne de contact"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'SuggestionThirdParty',
|
||||
components: {
|
||||
OnTheFly
|
||||
},
|
||||
props: ['item']
|
||||
props: ['item'],
|
||||
i18n,
|
||||
computed: {
|
||||
hasAddress() {
|
||||
if (this.$props.item.result.address !== null) {
|
||||
return true;
|
||||
}
|
||||
if (this.$props.item.result.parent !== null) {
|
||||
this.$props.item.result.parent.address !== null;
|
||||
}
|
||||
},
|
||||
hasParent() {
|
||||
return this.$props.item.result.parent !== null;
|
||||
},
|
||||
getAddress() {
|
||||
if (this.$props.item.result.address !== null) {
|
||||
return this.$props.item.result.address;
|
||||
}
|
||||
if (this.$props.item.result.parent.address !== null) {
|
||||
return this.$props.item.result.parent.address;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tpartycontainer {
|
||||
.tpartyparent {
|
||||
.name {
|
||||
font-weight: bold;
|
||||
font-variant: all-small-caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -71,7 +71,7 @@
|
||||
|
||||
<div class="col-md-6 location mb-5">
|
||||
{% if accompanyingCourse.locationStatus == 'person' %}
|
||||
<h5>{{ 'This course is located by'|trans }}</h5>
|
||||
<h2>{{ 'This course is located by'|trans }}</h2>
|
||||
<h4>{{ accompanyingCourse.personLocation|chill_entity_render_string }}</h4>
|
||||
{% elseif accompanyingCourse.locationStatus == 'address' %}
|
||||
<h4>{{ 'This course has a temporarily location'|trans }}</h4>
|
||||
@ -82,97 +82,9 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
{# DISABLED
|
||||
<h1>{{ 'Resume Accompanying Course'|trans }}</h1>
|
||||
|
||||
<div class="associated-persons mb-5">
|
||||
<h2 class="mb-3">{{ 'Associated peoples'|trans }}</h2>
|
||||
<div class="flex-table mb-3">
|
||||
{% for participation in accompanyingCourse.participations %}
|
||||
{% if participation.enddate is null %}
|
||||
<div class="item-bloc">
|
||||
{{ participation.person|chill_entity_render_box({
|
||||
'render': 'bloc', 'addLink': false, 'addInfo': true, 'addAltNames': false,
|
||||
'customButtons': { 'before': _self.button_person(participation.person) }
|
||||
}) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="location mb-5">
|
||||
<h2 class="mb-3">{{ 'Accompanying course location'|trans }}</h2>
|
||||
|
||||
{% if accompanyingCourse.locationStatus == 'person' %}
|
||||
<p>{{ 'This course is located by'|trans }}
|
||||
<b>{{ accompanyingCourse.personLocation|chill_entity_render_string }}</b>
|
||||
</p>
|
||||
{% elseif accompanyingCourse.locationStatus == 'address' %}
|
||||
<p>{{ 'This course has a temporarily location'|trans }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if accompanyingCourse.locationStatus != 'none' %}
|
||||
<div class="flex-table">
|
||||
<div class="item-bloc">
|
||||
{{ accompanyingCourse.location|chill_entity_render_box }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="requestor mb-5">
|
||||
<h2 class="mb-3">{{ 'Requestor'|trans }}</h2>
|
||||
{% if accompanyingCourse.requestorPerson is not empty %}
|
||||
{% set requestor = accompanyingCourse.requestorPerson %}
|
||||
{% set info = true %}
|
||||
{% elseif accompanyingCourse.requestor is not empty %}
|
||||
{% set requestor = accompanyingCourse.requestorThirdParty %}
|
||||
{% set info = false %}
|
||||
{% endif %}
|
||||
{% if accompanyingCourse.requestor == null %}
|
||||
<p class="chill-no-data-statement">{{ 'Any requestor to this accompanying course'|trans }}</p>
|
||||
{% else %}
|
||||
<div class="flex-bloc row row-cols-1 g-0">
|
||||
<div class="item-bloc col">
|
||||
{{ requestor|chill_entity_render_box({
|
||||
'render': 'bloc', 'addLink': false, 'addEntity': true, 'addInfo': info, 'addAltNames': false
|
||||
}) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="resources mb-5">
|
||||
<h2 class="mb-3">{{ 'Resources'|trans }}</h2>
|
||||
{% if accompanyingCourse.resources|length == 0 %}
|
||||
<p class="chill-no-data-statement">{{ 'Any resource for this accompanying course'|trans }}</p>
|
||||
{% else %}
|
||||
<div class="flex-bloc row row-cols-1 row-cols-sm-2 row-cols-xl-3 row-cols-xxl-4 g-0">
|
||||
{% for r in accompanyingCourse.resources %}
|
||||
<div class="item-bloc col">
|
||||
{% if r.person %}
|
||||
{{ r.person|chill_entity_render_box({
|
||||
'render': 'bloc', 'addLink': false, 'addEntity': true, 'addInfo': true, 'addAltNames': false
|
||||
}) }}
|
||||
{% endif %}
|
||||
{% if r.thirdParty %}
|
||||
{{ r.thirdParty|chill_entity_render_box({
|
||||
'render': 'bloc', 'addLink': false, 'addEntity': true, 'addInfo': false
|
||||
}) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
#}
|
||||
<div class="mt-5"></div>
|
||||
|
||||
<div class="social-actions mb-5">
|
||||
<h2 class="mb-3">{{ 'Social actions'|trans }}</h2>
|
||||
{% include 'ChillPersonBundle:AccompanyingCourseWork:list_by_accompanying_period.html.twig' with {'buttonText': false } %}
|
||||
<h2 class="mb-3">{{ 'Last social actions'|trans }}</h2>
|
||||
{% include 'ChillPersonBundle:AccompanyingCourseWork:list_recent_by_accompanying_period.html.twig' with {'buttonText': false } %}
|
||||
</div>
|
||||
|
||||
{% block contentActivity %}
|
||||
@ -189,9 +101,9 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ 'Activity list' |trans }}</h2>
|
||||
<h2 class="mb-3">{{ 'Last activities' |trans }}</h2>
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with { 'context': 'accompanyingCourse', 'no_action': true } %}
|
||||
{% include 'ChillActivityBundle:Activity:list_recent.html.twig' with { 'context': 'accompanyingCourse', 'no_action': true } %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user