diff --git a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_address.scss b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_address.scss index 1ee37632f..afe4e573f 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_address.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_address.scss @@ -9,6 +9,12 @@ div.chill_address { margin: 0 0 0 1.5em; text-indent: -1.5em; } + + &.chill_address_address--multiline { + p { + display: block; + } + } } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_record_actions.scss b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_record_actions.scss index 64ee66077..ccbc5912a 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_record_actions.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/modules/scratch/custom/_record_actions.scss @@ -9,6 +9,11 @@ ul.record_actions li { ul.record_actions, ul.record_actions_column { display: flex; justify-content: flex-end; + + &.record_actions--left { + justify-content: flex-start; + } + padding: 0.5em 0; flex-wrap: wrap-reverse; diff --git a/src/Bundle/ChillMainBundle/Resources/views/Address/entity_render.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Address/entity_render.html.twig new file mode 100644 index 000000000..fa7a13645 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Address/entity_render.html.twig @@ -0,0 +1,16 @@ +
+ {% if options['has_no_address'] == true and address.isNoAddress == true %} +
{{ 'address.consider homeless'|trans }}
+ {% endif %} +
+ {% if address.street is not empty %}

{{ address.street }}

{% endif %} + {% if address.streetNumber is not empty %}

{{ address.streetNumber }}

{% endif %} + {% if address.postCode is not empty %} +

{{ address.postCode.code }} {{ address.postCode.name }}

+

{{ address.postCode.country.name|localize_translatable_string }}

+ {% endif %} +
+{%- if options['with_valid_from'] == true -%} +{{ 'Since %date%'|trans( { '%date%' : address.validFrom|format_date('long') } ) }} +{%- endif -%} +
diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php new file mode 100644 index 000000000..90a707e40 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php @@ -0,0 +1,67 @@ + true, + 'has_no_address' => false, + 'multiline' => true, + ]; + + public function __construct(EngineInterface $templating) + { + $this->templating = $templating; + } + + /** + * {@inheritDoc} + */ + public function supports($entity, array $options): bool + { + return $entity instanceof Address; + } + + /** + * @param Address addr + */ + public function renderString($addr, array $options): string + { + $lines = []; + if (!empty($addr->getStreet())) { + $lines[0] = $addr->getStreet(); + } + if (!empty($addr->getStreetNumber())) { + $lines[0] .= ", ".$addr->getStreetNumber(); + } + if (!empty($addr->getPostcode())) { + $lines[1] = \strtr("{postcode} {label}", [ + '{postcode}' => $addr->getPostcode()->getCode(), + '{label}' => $addr->getPostcode()->getName() + ]); + } + + return implode(" - ", $lines); + } + + /** + * {@inheritDoc} + * @param Address addr + */ + public function renderBox($addr, array $options): string + { + $options = \array_merge(self::DEFAULT_OPTIONS, $options); + + return $this->templating + ->render('@ChillMain/Address/entity_render.html.twig', [ + 'address' => $addr, + 'options' => $options + ]); + } +} diff --git a/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php new file mode 100644 index 000000000..79551d23c --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Templating/Entity/AddressRenderTest.php @@ -0,0 +1,55 @@ +get(EngineInterface::class); + $renderer = new AddressRender($engine); + + $this->assertEquals($expectedString, $renderer->renderString($addr, [])); + return; + $this->assertIsString($renderer->renderBox($addr, [])); + } + + + public function addressDataProvider(): \Iterator + { + $addr = new Address(); + $country = (new Country()) + ->setName([ "fr" => "Pays" ]) + ->setCountryCode("BE") + ; + $postCode = new PostalCode(); + $postCode->setName("Locality") + ->setCode("012345") + ->setCountry($country) + ; + + $addr->setStreet("Rue ABC") + ->setStreetNumber("5") + ->setPostcode($postCode) + ; + + yield[ $addr, "Rue ABC, 5 - 012345 Locality"]; + } + +} diff --git a/src/Bundle/ChillMainBundle/config/services/templating.yaml b/src/Bundle/ChillMainBundle/config/services/templating.yaml index 29dc676d1..9d103f690 100644 --- a/src/Bundle/ChillMainBundle/config/services/templating.yaml +++ b/src/Bundle/ChillMainBundle/config/services/templating.yaml @@ -41,3 +41,10 @@ services: Chill\MainBundle\Templating\ChillMarkdownRenderExtension: tags: - { name: twig.extension } + + Chill\MainBundle\Templating\Entity\AddressRender: + arguments: + - '@Symfony\Component\Templating\EngineInterface' + tags: + - { name: 'chill.render_entity' } + diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 1afa6278c..a4fb185fb 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -421,6 +421,31 @@ class Person implements HasCenterInterface return $this->accompanyingPeriodParticipations; } + /** + * Return a collection of participation, where the participation + * is still opened, not a draft, and the period is still opened + */ + public function getOpenedParticipations(): Collection + { + // create a criteria for filtering easily + $criteria = Criteria::create(); + $criteria + ->andWhere(Criteria::expr()->eq('endDate', NULL)) + ->orWhere(Criteria::expr()->gt('endDate', new \DateTime('now'))) + ; + + return $this->getAccompanyingPeriodParticipations() + ->matching($criteria) + ->filter(function (AccompanyingPeriodParticipation $app) { + $period = $app->getAccompanyingPeriod(); + return ( + NULL === $period->getClosingDate() + || new \DateTime('now') < $period->getClosingDate() + ) + && AccompanyingPeriod::STEP_DRAFT !== $period->getStep(); + }); + } + /** * Get the accompanying periods of a give person with the chronological order. */ diff --git a/src/Bundle/ChillPersonBundle/Resources/public/index.js b/src/Bundle/ChillPersonBundle/Resources/public/index.js index f4bcba7fb..e3563b4ff 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/index.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/index.js @@ -1 +1,2 @@ -require('./sass/person.scss'); \ No newline at end of file +require('./sass/person.scss'); +require('./sass/person_with_period.scss'); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/sass/index.js b/src/Bundle/ChillPersonBundle/Resources/public/sass/index.js index 35945c7ff..89e749e5c 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/sass/index.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/sass/index.js @@ -1,5 +1,5 @@ require('./phone-alt-solid.svg'); require('./mobile-alt-solid.svg'); require('./person_by_phonenumber.scss'); - +require('./person_with_period.scss'); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/sass/person_with_period.scss b/src/Bundle/ChillPersonBundle/Resources/public/sass/person_with_period.scss new file mode 100644 index 000000000..7d61483db --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/sass/person_with_period.scss @@ -0,0 +1,68 @@ +.person-list--with-period { + .person-list--with-period__item { + margin-bottom: 0; + padding: 1em 1em 2em 1em; + &:nth-last-of-type { + padding-bottom: 1em; + } + + .chill-entity__person { + .chill-entity__person__first-name, + .chill-entity__person__last-name { + font-size: 1.3em; + font-weight: 700; + } + } + + & > div { + display: flex; + } + @media screen and (min-width: 720px) { + & > div { + flex-direction: row; + + .person-list--with-period__item__box-where { + align-self: flex-end; + margin-left: auto; + width: 33%; + + text-align: right; + } + } + } + + @media screen and (max-width: 720px) { + & > div { + flex-direction: column; + } + } + + @media screen and (max-width: 460px) { + .person-list--with-period__item__box-where__center { + display: none; + } + .chill_address { + .street { + display: none; + } + + .country { + display: none; + } + } + } + + ul.person-list--with-period__item__periods { + list-style-type: none; + padding: 0; + margin: 0; + + li { + + } + } + } + .person-list--with-period__item:hover { + background-color: var(--chill-llight-gray); + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig new file mode 100644 index 000000000..afcd2799c --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Entity/person.html.twig @@ -0,0 +1,15 @@ + + {%- if addLink and is_granted('CHILL_PERSON_SEE', person) -%} + {%- set showLink = true -%}{%- endif -%} + {{ person.firstName }} + {{ person.lastName }} + {%- if addAltNames -%} + {%- for n in person.altNames -%} + {%- if loop.first -%}({% else %} {%- endif -%} + + {{ n.label }} + + {%- if loop.last %}) {% endif -%} + {%- endfor -%} + {%- endif -%} + {%- if showLink is defined -%}{%- endif -%} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Entity/social_issue.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Entity/social_issue.html.twig new file mode 100644 index 000000000..2db894e3c --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Entity/social_issue.html.twig @@ -0,0 +1,13 @@ +{% set reversed_parents = parents|reverse %} + + + {%- for p in reversed_parents %} + + {%- endfor -%} + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig new file mode 100644 index 000000000..da571d173 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/list_with_period.html.twig @@ -0,0 +1,208 @@ +

{{ title|default('Person search results')|trans }}

+ +

+ {{ '%total% persons matching the search pattern:'|transchoice( total, { '%total%' : total}) }} + + {{ pattern }} + +

+ +

{{ 'Results %start%-%end% of %total%'|trans({ '%start%' : start, '%end%': start + persons|length, '%total%' : total } ) }}

+ + + + +{% if persons|length > 0 %} + +
+ {% for person in persons %} +
+
+
+
+ {{ person|chill_entity_render_box({'addLink': true}) }} + {{ 'Born the %date%'|transchoice(person.genderNumeric, { '%date%': person.birthdate|format_date("medium") }) }} +
+
+ +
+
+
+ {{ person.center }} + {% if person.getLastAddress is not null %} + {{ person.getLastAddress|chill_entity_render_box({'with_valid_from': false}) }} + {% else %} + {{ 'No address'|trans }} + {% endif %} + {% if person.mobilenumber is not empty %} + {{ person.mobilenumber|chill_format_phonenumber }} + {% endif %} + {% if person.phonenumber is not empty %} + {{ person.phonenumber|chill_format_phonenumber }} + {% endif %} + +
+
+ + {#- 'apps' is for AccompanyingPeriodParticipationS #} + {#- filter using acl -#} + {%- set apps = [] %} + {%- for app in person.openedParticipations %} + {%- if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_SEE', app.accompanyingPeriod) %} + {%- set apps = apps|merge([app]) %} + {%- endif %} + {%- endfor %} + {% if apps|length > 0 %} + + {% endif %} + +
+ {% endfor %} +
+ + {# + + + + + + + + + + + {% for person in persons %} + + + + + + + {% endfor %} + +
{% trans %}Name{% endtrans %}{% trans %}Date of birth{% endtrans %}{% trans %}Nationality{% endtrans %} 
+ {% set is_open = person.isOpen() %} + + {{ person|chill_entity_render_box }} + {% apply spaceless %} + {% if chill_person.fields.accompanying_period == 'visible' %} + {% if is_open == false %} + + {% else %} + + {% endif %} + {% endif %} + {% endapply %} + + + {% if person.birthdate is not null %} + {{ person.birthdate|format_date('long') }} + {% else %}{{ 'Unknown date of birth'|trans }}{% endif %} + + {% if person.nationality is not null %} + {{person.nationality.name | localize_translatable_string }} + {% else %} + {{ 'Without nationality'|trans }} + {% endif %} + +
    +
  • + {% if is_granted('CHILL_PERSON_UPDATE', person) %} +
  • + {% endif %} +
+
+ + #} + + +{% else %} + +{% endif %} + +{% if preview == false %} +{{ chill_pagination(paginator) }} +{% endif %} + diff --git a/src/Bundle/ChillPersonBundle/Search/PersonSearch.php b/src/Bundle/ChillPersonBundle/Search/PersonSearch.php index 34f79bb87..fe938999a 100644 --- a/src/Bundle/ChillPersonBundle/Search/PersonSearch.php +++ b/src/Bundle/ChillPersonBundle/Search/PersonSearch.php @@ -120,7 +120,7 @@ class PersonSearch extends AbstractSearch implements ContainerAwareInterface, $paginator = $this->paginatorFactory->create($total); if ($format === 'html') { - return $this->container->get('templating')->render('ChillPersonBundle:Person:list.html.twig', + return $this->container->get('templating')->render('@ChillPerson/Person/list_with_period.html.twig', array( 'persons' => $this->search($terms, $start, $limit, $options), 'pattern' => $this->recomposePattern($terms, array('nationality', diff --git a/src/Bundle/ChillPersonBundle/Templating/Entity/SocialIssueRender.php b/src/Bundle/ChillPersonBundle/Templating/Entity/SocialIssueRender.php index 4a7ed0cb5..1923325f9 100644 --- a/src/Bundle/ChillPersonBundle/Templating/Entity/SocialIssueRender.php +++ b/src/Bundle/ChillPersonBundle/Templating/Entity/SocialIssueRender.php @@ -5,10 +5,12 @@ namespace Chill\PersonBundle\Templating\Entity; use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface; use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Symfony\Component\Templating\EngineInterface; class SocialIssueRender implements ChillEntityRenderInterface { private TranslatableStringHelper $translatableStringHelper; + private EngineInterface $engine; public const SEPARATOR_KEY = 'default.separator'; @@ -16,14 +18,15 @@ class SocialIssueRender implements ChillEntityRenderInterface self::SEPARATOR_KEY => ' > ', ]; - public function __construct(TranslatableStringHelper $translatableStringHelper) + public function __construct(TranslatableStringHelper $translatableStringHelper, EngineInterface $engine) { $this->translatableStringHelper = $translatableStringHelper; + $this->engine = $engine; } public function supports($entity, array $options): bool { - return $entity instanceof SocialIssueRender; + return $entity instanceof SocialIssue; } public function renderString($socialIssue, array $options): string @@ -42,9 +45,27 @@ class SocialIssueRender implements ChillEntityRenderInterface return $str; } - - public function renderBox($entity, array $options): string + + protected function buildParents($socialIssue): array { - return "renderBox not implemented for social issue"; + $parents = []; + while ($socialIssue->hasParent()) { + $socialIssue = $parents[] = $socialIssue->getParent(); + } + + return $parents; + } + + public function renderBox($socialIssue, array $options): string + { + $options = \array_merge(self::DEFAULT_ARGS, $options); + // give some help to twig: an array of parents + $parents = $this->buildParents($socialIssue); + + return $this->engine->render('@ChillPerson/Entity/social_issue.html.twig', [ + 'socialIssue' => $socialIssue, + 'parents' => $parents, + 'options' => $options + ]); } } diff --git a/src/Bundle/ChillPersonBundle/config/services/templating.yaml b/src/Bundle/ChillPersonBundle/config/services/templating.yaml index 37e904884..aa5dd677a 100644 --- a/src/Bundle/ChillPersonBundle/config/services/templating.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/templating.yaml @@ -17,3 +17,6 @@ services: Chill\PersonBundle\Templating\Entity\SocialIssueRender: arguments: $translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper' + $engine: '@Symfony\Component\Templating\EngineInterface' + tags: + - 'chill.render_entity' diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 30536eaa7..ebb62b6ad 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -46,7 +46,7 @@ Add new phone: Ajouter un numéro de téléphone Remove phone: Supprimer 'Notes on contact information': 'Remarques sur les informations de contact' 'Remarks': 'Remarques' -'{0} Born the %date% | {1} Born the %date%': '{0} Né le %date% | {1} Née le %date%' +'Born the %date%': '{0} Né le %date% | {1} Née le %date%' 'Spoken languages': 'Langues parlées' 'Unknown spoken languages': 'Langues parlées inconnues' Male: Homme @@ -125,6 +125,8 @@ Reset: 'Remise à zéro' 'Person search results': 'Recherche de personnes' Person search results by phonenumber: Recherche de personnes par numéro de téléphone 'Search within persons': 'Recherche parmi les personnes' +Open person file: Ouvrir le dossier +and %number% other: '{0} et aucun autre| {1} et une autre |]1, Inf] et %number% autres' '%total% persons matching the search pattern:': '{0} Aucune personne ne correspond aux termes de recherche : | {1} Une personne a été trouvée par la recherche : | ]1,Inf] %total% personnes correspondent aux termes de recherche :' 'Last opening since %last_opening%': 'Dernière ouverture le %last_opening%.' 'Person accompanying period - %name%': 'Historique du dossier - %name%'