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/public/scss/chillmain.scss b/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss index 6aa0e1c8d..b91aadb42 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/scss/chillmain.scss @@ -1,12 +1,48 @@ /* * NOTE 2021.04 - * scss/chill.scss is the main sass file for the new chill.2 + * scss/chillmain.scss is the main sass file for the new chill.2 * scratch will be replaced by bootstrap, please avoid to edit in modules/scratch/_custom.scss * - * when possible, try to use bootstrap class naming + * when possible, try to use bootstrap html class */ + +/* [hack] /!\ Contourne le positionnement problématique du div#content_conainter suivant, + * car sa position: relative le place au-dessus du bandeau et les liens sont incliquables */ +div.subheader { + height: 130px; +} + /* + * Specific rules + */ + +// [scratch] un bouton 'disabled' non clickable +.sc-button { + &.disabled { + cursor: default; + &.bt-remove { + background-color: #d9d9d9; + } + } +} + +// [debug] un affichage discret pour le debug +.discret { + color: grey; + margin-right: 1em; +} + +// reserre la hauteur des rangées de tableau (ul.record_actions prennait trop de place) +table { + ul.record_actions { + margin: 0; + padding: 0.5em; + } +} + +/* + * ACCOMPANYING_COURSE * Header custom for Accompanying Course */ @@ -25,7 +61,6 @@ div#header-accompanying_course-name { } } } - div#header-accompanying_course-details { background: none repeat scroll 0 0 #718596ab; color: #FFF; @@ -33,31 +68,158 @@ div#header-accompanying_course-details { padding-bottom: 1em; } -/* /!\ Contourne le positionnement problématique du div#content_conainter suivant, - * car sa position: relative le place au-dessus du bandeau et les liens sont incliquables */ -div.subheader { - height: 130px; +/* +* FLEX RESPONSIVE TABLE/BLOCK PRESENTATION +*/ +div.flex-bloc, +div.flex-table { + h2, h3, h4, dl, p { + margin: 0; + } + h2, h3, h4 { + color: var(--chill-blue); + } } -//// SCRATCH BUTTONS -.sc-button { - &.disabled { - cursor: default; - &.bt-remove { - background-color: #d9d9d9; +/* +* Bloc appearance +*/ +div.flex-bloc { + box-sizing: border-box; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: stretch; + align-content: stretch; + + div.item-bloc { + flex-grow: 0; flex-shrink: 1; flex-basis: 50%; + + margin: 0; + border: 1px solid #000; + padding: 1em; + + border-top: 0; + &:nth-child(1), &:nth-child(2) { + border-top: 1px solid #000; + } + border-left: 0; + &:nth-child(odd) { + border-left: 1px solid #000; + } + + //background-color: #e6e6e6; + display: flex; + flex-direction: column; + + div.item-row { + flex-grow: 1; flex-shrink: 1; flex-basis: auto; + display: flex; + flex-direction: column; + + div.item-col { + &:first-child { + flex-grow: 0; flex-shrink: 0; flex-basis: auto; + } + &:last-child { + flex-grow: 1; flex-shrink: 1; flex-basis: auto; + display: flex; + + .list-content { // ul, dl, or div + } + ul.record_actions { + margin: 0; + align-self: flex-end; + flex-grow: 1; flex-shrink: 0; flex-basis: auto; + li { + margin-right: 5px; + } + } + } + } + } + } + @media only screen and (max-width: 945px) { margin: auto -0.2em; } + @media only screen and (max-width: 935px) { margin: auto -0.5em; } + @media only screen and (max-width: 920px) { margin: auto -0.9em; } + @media only screen and (max-width: 900px) { + flex-direction: column; + margin: auto 0; + div.item-bloc { + border-left: 1px solid #000; + &:nth-child(2) { + border-top: 0; + } } } } -//// à ranger -.discret { - color: grey; - margin-right: 1em; -} +/* +* Table appearance +*/ +div.flex-table { + display: flex; + flex-direction: column; + align-items: stretch; + align-content: stretch; + + div.item-bloc { + display: flex; + flex-direction: column; + padding: 1em; + border: 1px solid #000; + border-top: 0; + &:first-child { + border-top: 1px solid #000; + } + &:nth-child(even) { + background-color: #e6e6e6; + } -table { - ul.record_actions { - margin: 0; - padding: 0.5em; + div.item-row { + display: flex; + flex-direction: row; + &:not(:first-child) { + margin-top: 0.5em; + border-top: 1px dotted #0000004f; + padding-top: 0.5em; + flex-direction: column; + } + + div.item-col { + &:first-child { + flex-grow: 0; flex-shrink: 0; flex-basis: 33%; + } + &:last-child { + flex-grow: 1; flex-shrink: 1; flex-basis: auto; + display: flex; + justify-content: flex-end; + + .list-content { // ul, dl, or div + } + ul.record_actions { + margin: 0; + align-self: flex-start; + flex-grow: 1; flex-shrink: 0; flex-basis: auto; + li { + margin-right: 5px; + } + } + } + } + @media only screen and (max-width: 900px) { + flex-direction: column; + div.item-col { + &:last-child { + ul.record_actions { + align-self: flex-end; + } + } + } + } + + // neutralize + div.chill_address div.chill_address_address p { text-indent: 0; } + } } -} +} 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 @@ +
{{ address.street }}
{% endif %} {% if address.streetNumber is not empty %}{{ address.streetNumber }}
{% endif %} {% if address.postCode is not empty %} 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/Controller/AccompanyingCourseController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php index 6786cb05f..e5b0cdda7 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseController.php @@ -72,7 +72,7 @@ class AccompanyingCourseController extends Controller $em->persist($period); $em->flush(); - return $this->redirectToRoute('chill_person_accompanying_course_show', [ + return $this->redirectToRoute('chill_person_accompanying_course_edit', [ 'accompanying_period_id' => $period->getId() ]); @@ -92,17 +92,16 @@ class AccompanyingCourseController extends Controller } /** - * Show page of Accompanying Course section + * Edit page of Accompanying Course section * - * the page show all blocks except one active edit block, managed by vuejs component - * that's why title of page is 'edit accompanying course' + * the page edit all blocks managed by vuejs component * - * @Route("/{_locale}/parcours/{accompanying_period_id}/show", name="chill_person_accompanying_course_show") + * @Route("/{_locale}/parcours/{accompanying_period_id}/edit", name="chill_person_accompanying_course_edit") * @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"}) */ - public function showAction(AccompanyingPeriod $accompanyingCourse): Response + public function editAction(AccompanyingPeriod $accompanyingCourse): Response { - return $this->render('@ChillPerson/AccompanyingCourse/show.html.twig', [ + return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [ 'accompanyingCourse' => $accompanyingCourse ]); } 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/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index e9ce20b53..49543c42d 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -43,7 +43,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface ->setExtras(['order' => 10]); $menu->addChild($this->translator->trans('Edit Accompanying Course'), [ - 'route' => 'chill_person_accompanying_course_show', + 'route' => 'chill_person_accompanying_course_edit', 'routeParameters' => [ 'accompanying_period_id' => $period->getId() ]]) 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..6f52d2cae --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/sass/person_with_period.scss @@ -0,0 +1,50 @@ +/// complete and overwrite flex-table in chillmain.scss +div.list-with-period { + div.person { + ul.record_actions { + li { + margin-right: 0 !important; + } + } + } + div.periods { + div.header, + div.list-content { + width: calc(100% - 40px); + margin-left: 40px; + } + div.header { + position: relative; + a.sc-button { + position: absolute; + width: 30px; + height: 30px; + top: 10px; + left: -40px; + padding: 0; + i { + padding: 5px; + } + } + abbr.referrer { + font-size: 70%; + } + span.user { + margin-left: 1em; + } + } + div.list-content { + span.more { + font-style: italic; + } + } + } +} + +.chill-entity__person { + .chill-entity__person__first-name, + .chill-entity__person__last-name { + font-size: 1.3em; + font-weight: 700; + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue index c6783677a..32fbb86c2 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Requestor.vue @@ -3,45 +3,47 @@-{{ accompanyingCourse.id }} -{{ accompanyingCourse.openingDate|format_date('short') }} -{{ accompanyingCourse.closingDate|format_date('short') }} -{{ accompanyingCourse.closingMotive|chill_entity_render_box }} -{{ accompanyingCourse.remark|raw }} -{{ accompanyingCourse.user }} -usagers: -{% for p in accompanyingCourse.participations %} - {{ p.person.id }} | {{ p.person.fullnamecanonical }} | {{ p.startdate|format_date('short') }} | {{ p.enddate|format_date('short') }} -{% endfor %} -+ {# start test flex-table #} +
+ + {{ 'Née le ' ~ p.person.birthdate|format_date('short') }} +
++ {% set born = (p.person.gender == 'woman') ? 'née': 'né' %} + {% set gender = (p.person.gender == 'woman') ? 'fa-venus' : + (p.person.gender == 'man') ? 'fa-mars' : 'fa-neuter' %} + {% set genderTitle = (p.person.gender == 'woman') ? 'femme' : + (p.person.gender == 'homme') ? 'fa-mars' : 'neutre' %} + {{ born ~ ' le ' ~ p.person.birthdate|format_date('short') }} +
++ {% set born = (r.person.gender == 'woman') ? 'née': 'né' %} + {% set gender = (r.person.gender == 'woman') ? 'fa-venus' : + (r.person.gender == 'man') ? 'fa-mars' : 'fa-neuter' %} + {% set genderTitle = (r.person.gender == 'woman') ? 'femme' : + (r.person.gender == 'homme') ? 'fa-mars' : 'neutre' %} + {{ born ~ ' le ' ~ r.person.birthdate|format_date('short') }} +
++ {{ '%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 } ) }}
+ +