Merge remote-tracking branch 'origin/master' into issue406_truncate_comment

This commit is contained in:
2022-01-26 14:03:49 +01:00
26 changed files with 1331 additions and 16 deletions

View File

@@ -0,0 +1,178 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Entity\Person\PersonResource;
use Chill\PersonBundle\Form\PersonResourceType;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Repository\PersonResourceRepository;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;
final class PersonResourceController extends AbstractController
{
private EntityManagerInterface $em;
private PersonRepository $personRepository;
private PersonResourceRepository $personResourceRepository;
private TranslatorInterface $translator;
public function __construct(
PersonResourceRepository $personResourceRepository,
PersonRepository $personRepository,
EntityManagerInterface $em,
TranslatorInterface $translator
) {
$this->personResourceRepository = $personResourceRepository;
$this->personRepository = $personRepository;
$this->em = $em;
$this->translator = $translator;
}
public function deleteAction(Request $request, $person_id, $resource_id): Response
{
$personOwner = $this->personRepository->find($person_id);
$resource = $this->personResourceRepository->find($resource_id);
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $personOwner);
if (null === $resource) {
throw $this->createNotFoundException('Unable to find Resource entity.');
}
$form = $this->createFormBuilder()
->setAction($this->generateUrl('chill_person_resource_delete', [
'resource_id' => $resource_id,
'person_id' => $person_id,
]))
->setMethod('DELETE')
->add('submit', SubmitType::class, ['label' => 'Delete'])
->getForm();
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->em->remove($resource);
$this->em->flush();
$this->addFlash('success', $this->translator
->trans('The resource has been successfully removed.'));
return $this->redirectToRoute('chill_person_resource_list', [
'person_id' => $personOwner->getId(),
]);
}
}
return $this->render(
'ChillPersonBundle:PersonResource:delete.html.twig',
[
'person' => $personOwner,
'resource' => $resource,
'form' => $form->createView(),
]
);
}
public function editAction(Request $request, $resource_id, $person_id): Response
{
$resource = $this->personResourceRepository->find($resource_id);
$personOwner = $this->personRepository->find($person_id);
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $personOwner);
if (null === $resource) {
throw $this->createNotFoundException('Unable to find Resource entity.');
}
$form = $this->createForm(PersonResourceType::class, $resource);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->em->persist($resource);
$this->em->flush();
return $this->redirectToRoute('chill_person_resource_list', [
'person_id' => $personOwner->getId(),
]);
}
dump($resource);
return $this->render(
'ChillPersonBundle:PersonResource:edit.html.twig',
[
'person' => $personOwner,
'resource' => $resource,
'form' => $form->createView(),
'action' => 'edit',
]
);
}
public function listAction(Request $request, $person_id)
{
$personOwner = $this->personRepository->find($person_id);
$this->denyAccessUnlessGranted(PersonVoter::SEE, $personOwner);
$personResources = [];
$personResources = $this->personResourceRepository->findBy(['personOwner' => $personOwner->getId()]);
$form = $this->createForm(PersonResourceType::class);
$form->handleRequest($request);
if ($request->getMethod() === Request::METHOD_POST && $form->isValid()) {
$this->denyAccessUnlessGranted(PersonVoter::CREATE, $personOwner);
$personResource = new PersonResource();
$person = $form['person']->getData();
$thirdparty = $form['thirdparty']->getData();
$freetext = $form['freetext']->getData();
$comment = $form['comment']->getData();
$kind = $form['kind']->getData();
$personResource->setKind($kind);
$personResource->setPerson($person);
$personResource->setThirdParty($thirdparty);
$personResource->setFreeText($freetext);
$personResource->setComment($comment);
$personResource->setPersonOwner($personOwner);
$this->em->persist($personResource);
$this->em->flush();
return $this->redirectToRoute('chill_person_resource_list', [
'person_id' => $personOwner->getId(),
]);
}
return $this->render(
'ChillPersonBundle:PersonResource:list.html.twig',
[
'person' => $personOwner,
'personResources' => $personResources,
'form' => $form->createView(),
]
);
}
}

View File

@@ -0,0 +1,275 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\Person;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* @ORM\Entity
* @ORM\Table(name="chill_person_resource")
* @DiscriminatorMap(typeProperty="type", mapping={
* "personResource": personResource::class
* })
*/
class PersonResource implements TrackCreationInterface, TrackUpdateInterface
{
/**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
* @Groups({"read"})
*/
private CommentEmbeddable $comment;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=false)
*/
private User $createdBy;
/**
* @ORM\Column(type="text", nullable=true)
* @Groups({"read"})
*/
private $freeText;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\ManyToOne(targetEntity=PersonResourceKind::class, inversedBy="personResources")
* @ORM\JoinColumn(nullable=true)
* @Groups({"read"})
*/
private $kind;
/**
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="personResources")
* @ORM\JoinColumn(nullable=true)
* @Groups({"read"})
*/
private ?Person $person = null;
/**
* @ORM\ManyToOne(targetEntity=Person::class)
* @ORM\JoinColumn(nullable=false)
* @Groups({"read"})
*/
private ?Person $personOwner = null;
/**
* @ORM\ManyToOne(targetEntity=ThirdParty::class, inversedBy="personResources")
* @ORM\JoinColumn(nullable=true)
* @Groups({"read"})
*/
private ?ThirdParty $thirdParty = null;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $updatedAt;
/**
* @ORM\ManyToOne(targetEntity=User::class)
*/
private User $updatedBy;
public function __construct()
{
$this->comment = new CommentEmbeddable();
}
public function getComment(): CommentEmbeddable
{
return $this->comment;
}
public function getCreatedAt(): ?DateTimeInterface
{
return $this->createdAt;
}
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
public function getFreeText(): ?string
{
return $this->freeText;
}
/**
* GETTERS.
*/
public function getId(): ?int
{
return $this->id;
}
public function getKind(): ?PersonResourceKind
{
return $this->kind;
}
public function getPerson(): ?Person
{
return $this->person;
}
public function getPersonOwner(): ?Person
{
return $this->personOwner;
}
public function getThirdParty(): ?ThirdParty
{
return $this->thirdParty;
}
public function getUpdatedAt(): ?DateTimeInterface
{
return $this->updatedAt;
}
public function getUpdatedBy(): ?User
{
return $this->updatedBy;
}
public function setComment(?CommentEmbeddable $comment): self
{
if (null === $comment) {
$this->comment->setComment('');
return $this;
}
$this->comment = $comment;
return $this;
}
public function setCreatedAt(DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function setCreatedBy(?User $createdBy): self
{
$this->createdBy = $createdBy;
return $this;
}
/**
* SETTERS.
*/
public function setFreeText(?string $freeText): self
{
$this->freeText = $freeText;
if ('' !== $freeText && null !== $freeText) {
$this->setPerson(null);
$this->setThirdParty(null);
}
return $this;
}
public function setKind(?PersonResourceKind $kind): self
{
$this->kind = $kind;
return $this;
}
public function setPerson(?Person $person): self
{
$this->person = $person;
if (null !== $person) {
$this->setFreeText('');
$this->setThirdParty(null);
}
return $this;
}
public function setPersonOwner(?Person $personOwner): self
{
$this->personOwner = $personOwner;
return $this;
}
public function setThirdParty(?ThirdParty $thirdParty): self
{
$this->thirdParty = $thirdParty;
if (null !== $thirdParty) {
$this->setFreeText('');
$this->setPerson(null);
}
return $this;
}
public function setUpdatedAt(DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function setUpdatedBy(?User $updatedBy): self
{
$this->updatedBy = $updatedBy;
return $this;
}
/**
* @Assert\Callback
*
* @param mixed $payload
*/
public function validate(ExecutionContextInterface $context, $payload)
{
if (null === $this->person && null === $this->thirdParty && null === $this->freeText) {
$context->buildViolation('You must associate at least one entity')
->atPath('person')
->addViolation();
}
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\Mapping as ORM;
/**
* **About denormalization**: this operation is operated by @see{AccompanyingPeriodResourdeNormalizer}.
*
* @ORM\Entity
* @ORM\Table(name="chill_person_resource_kind")
*/
class PersonResourceKind
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private int $id;
/**
* @ORM\Column(type="boolean")
*/
private bool $isActive = true;
/**
* @ORM\Column(type="json", length=255)
*/
private array $title;
public function getId(): ?int
{
return $this->id;
}
public function getIsActive(): bool
{
return $this->isActive;
}
public function getTitle(): ?array
{
return $this->title;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
public function setTitle(array $title): self
{
$this->title = $title;
return $this;
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Form;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\PersonBundle\Entity\Person\PersonResource;
use Chill\PersonBundle\Entity\Person\PersonResourceKind;
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Chill\PersonBundle\Templating\Entity\PersonRender;
use Chill\PersonBundle\Templating\Entity\ResourceKindRender;
use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType;
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;
final class PersonResourceType extends AbstractType
{
private PersonRender $personRender;
private ResourceKindRender $resourceKindRender;
private ThirdPartyRender $thirdPartyRender;
private TranslatorInterface $translator;
public function __construct(ResourceKindRender $resourceKindRender, PersonRender $personRender, ThirdPartyRender $thirdPartyRender, TranslatorInterface $translator)
{
$this->resourceKindRender = $resourceKindRender;
$this->personRender = $personRender;
$this->thirdPartyRender = $thirdPartyRender;
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('kind', EntityType::class, [
'label' => 'Type',
'required' => false,
'class' => PersonResourceKind::class,
'query_builder' => static function (EntityRepository $er) {
$qb = $er->createQueryBuilder('pr');
$qb->where($qb->expr()->eq('pr.isActive', 'TRUE'));
return $qb;
},
'placeholder' => $this->translator->trans('Select a type'),
'choice_label' => function (PersonResourceKind $personResourceKind) {
$options = [];
return $this->resourceKindRender->renderString($personResourceKind, $options);
},
])
->add('person', PickPersonDynamicType::class, [
'label' => 'Usager',
])
->add('thirdparty', PickThirdpartyDynamicType::class, [
'label' => 'Tiers',
])
->add('freetext', ChillTextareaType::class, [
'label' => 'Description libre',
'required' => false,
])
->add('comment', CommentType::class, [
'label' => 'Note',
'required' => false,
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => PersonResource::class,
]);
}
public function getBlockPrefix(): string
{
return 'chill_personbundle_person_resource';
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Form\Type;
use Chill\MainBundle\Form\Type\DataTransformer\EntityToJsonTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Pick user dymically, using vuejs module "AddPerson".
*/
class PickPersonDynamicType extends AbstractType
{
private DenormalizerInterface $denormalizer;
private SerializerInterface $serializer;
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
{
$this->denormalizer = $denormalizer;
$this->serializer = $serializer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addViewTransformer(new EntityToJsonTransformer($this->denormalizer, $this->serializer, $options['multiple'], 'person'));
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['person'];
$view->vars['uniqid'] = uniqid('pick_user_dyn');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
->setDefault('compound', false);
}
public function getBlockPrefix()
{
return 'pick_entity_dynamic';
}
}

View File

@@ -96,6 +96,16 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
'order' => 100,
]);
}
$menu->addChild($this->translator->trans('person_resources_menu'), [
'route' => 'chill_person_resource_list',
'routeParameters' => [
'person_id' => $parameters['person']->getId(),
],
])
->setExtras([
'order' => 99999,
]);
}
public static function getMenuIds(): array

View File

@@ -0,0 +1,61 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Repository;
use Chill\PersonBundle\Entity\Person\PersonResource;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class PersonResourceRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(PersonResource::class);
}
public function find($id): ?PersonResource
{
return $this->repository->find($id);
}
/**
* @return PersonResource[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @param mixed|null $limit
* @param mixed|null $offset
*
* @return PersonResource[]
*/
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function findOneBy(array $criteria): ?PersonResource
{
return $this->repository->findOneBy($criteria);
}
public function getClassName(): string
{
return PersonResource::class;
}
}

View File

@@ -0,0 +1,55 @@
import {ShowHide} from 'ChillMainAssets/lib/show_hide/show_hide.js';
window.addEventListener('DOMContentLoaded', function() {
let
personContainer = document.querySelector('#person-entity'),
entitySelector = document.querySelector('#entity-selector'),
freetextContainer = document.querySelector('#freetext-entity'),
thirdpartyContainer = document.querySelector('#thirdparty-entity')
;
if (null === entitySelector) {
return;
}
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [personContainer],
test: function(froms, event) {
for (let container of froms) {
return container.querySelector('input[value="person"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [thirdpartyContainer],
test: function(froms, event) {
for (let container of froms) {
return container.querySelector('input[value="thirdparty"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [freetextContainer],
test: function(froms, event) {
for (let container of froms) {
return container.querySelector('input[value="freetext"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
});

View File

@@ -0,0 +1,14 @@
<div class="col-md col-xxl">
<div id="collapseForm" class="collapse">
{% include "@ChillPerson/PersonResource/form.html.twig" %}
</div>
<ul class="record_actions sticky-form-buttons">
<li>
<button class="btn btn-primary btn-create change-icon" type="button" data-bs-toggle="collapse" data-bs-target="#collapseForm" aria-expanded="false" aria-controls="collapseForm">
{{ 'Add a person resource'|trans }}
</button>
</li>
</ul>
</div>

View File

@@ -0,0 +1,17 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_person_resource_list' %}
{# {% set person = person %} #}
{% block title 'Remove resource'|trans %}
{% block personcontent %}
{{ include('@ChillMain/Util/confirmation_template.html.twig',
{
'title' : 'Remove resource'|trans,
'confirm_question' : 'Are you sure you want to remove the resource for "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname } ),
'cancel_route' : 'chill_person_resource_list',
'cancel_parameters' : { 'person_id' : person.id },
'form' : form
} ) }}
{% endblock %}

View File

@@ -0,0 +1,23 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_person_resource_edit' %}
{% block js %}
{{ encore_entry_script_tags('page_person_resource_showhide_input') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('page_person_resource_showhide_input') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block title %}{{ 'edit resource'|trans|capitalize }}{% endblock %}
{% block personcontent %}
<h1 style="margin-bottom: 2rem;">{{ 'edit resource'|trans }}</h1>
{% include "@ChillPerson/PersonResource/form.html.twig" %}
{% endblock %}

View File

@@ -0,0 +1,78 @@
{{ form_start(form, {'attr' : {'id' : 'create-form'}}) }}
{{ form_row(form.kind) }}
<div id="linked-entity">
<fieldset class="mb-3">
<div class="row">
<legend class="col-sm-4 col-form-label">Associer un</legend>
<div class="col-sm-8">
<div id="entity-selector">
<div class="form-check">
{% if resource is defined and resource.person is not null %}
<input checked type="radio" id="chill_personbundle_person_resource_linkedEntity_0" name="linked-entity" class="form-check-input" value="person" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_0">Usager</label>
{% else %}
<input type="radio" id="chill_personbundle_person_resource_linkedEntity_0" name="linked-entity" class="form-check-input" value="person" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_0">Usager</label>
{% endif %}
</div>
<div class="form-check">
{% if resource is defined and resource.thirdparty is not null %}
<input checked type="radio" id="chill_personbundle_person_resource_linkedEntity_1" name="linked-entity" class="form-check-input" value="thirdparty" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_1">Tiers</label>
{% else %}
<input type="radio" id="chill_personbundle_person_resource_linkedEntity_1" name="linked-entity" class="form-check-input" value="thirdparty" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_1">Tiers</label>
{% endif %}
</div>
<div class="form-check">
{% if resource is defined and resource.freeText is not null %}
<input checked type="radio" id="chill_personbundle_person_resource_linkedEntity_2" name="linked-entity" class="form-check-input" value="freetext" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_2">Description libre</label>
{% else %}
<input type="radio" id="chill_personbundle_person_resource_linkedEntity_2" name="linked-entity" class="form-check-input" value="freetext" />
<label class="form-check-label" for="chill_personbundle_person_resource_linkedEntity_2">Description libre</label>
{% endif %}
</div>
</div>
</div>
</div>
</fieldset>
</div>
<div id="person-entity">
{{ form_row(form.person) }}
</div>
<div id="thirdparty-entity">
{{ form_row(form.thirdparty) }}
</div>
<div id="freetext-entity">
{{ form_row(form.freetext) }}
</div>
{{ form_row(form.comment) }}
{% if action is defined %}
<ul class="record_actions sticky-form-buttons">
<li class="edit">
<button class="btn btn-edit"
type="submit" id="newPersonResource">
{{ 'edit resource'|trans|capitalize }}
</button>
</li>
</ul>
{% else %}
<ul class="record_actions">
<li>
<button class="btn btn-create"
type="submit" id="newPersonResource">
{{ 'Save'|trans }}
</button>
</li>
</ul>
{% endif %}
{{ form_end(form) }}

View File

@@ -0,0 +1,101 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_person_resource_list' %}
{% block title %}{{ 'Person resources'|trans|capitalize ~ ' ' ~ person|chill_entity_render_string }}{% endblock %}
{% block js %}
{{ encore_entry_script_tags('page_person_resource_showhide_input') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('page_person_resource_showhide_input') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block personcontent %}
<h1>{{ 'List of resources'|trans }}</h1>
{% if personResources is not null %}
{% for resource in personResources %}
<div class="flex-table">
<div class="item-bloc">
<div class="item-row">
<div class="wrap-header">
<div class="wh-row">
<div class="wh-col">
{% if resource.person is not null %}
<div class="item-col">
<div class="denomination h3">
<span class="name">{{ resource.person }}</span>
<span class="badge rounded-pill bg-person">{{ 'person'|trans|capitalize }}</span>
</div>
</div>
{% elseif resource.thirdparty is not null %}
<div class="item-col">
<div class="denomination h3">
<span class="name">{{ resource.thirdparty }}</span>
<span class="badge rounded-pill bg-thirdparty">
{{ 'thirdparty'|trans|capitalize }}
<i class="fa fa-fw fa-user-md"></i>
</span>
</div>
</div>
{% else %}
<div class="item-col">
<div class="denomination h3">
<span>{{ resource.freetext }}</span>
</div>
</div>
{% endif %}
<div class="wh-col">
{% if resource.kind %}
<span>{{ resource.kind.title.fr|capitalize }}</span>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% if resource.comment.comment is not null %}
<div class="item-row separator">
<section class="chill-entity entity-comment-embeddable">
<blockquote class="chill-user-quote">
<div>{{ resource.comment.comment }}<div>
</blockquote>
</section>
</div>
{% endif %}
<div class="item-row separator">
<div class="item-col">
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_resource_edit', {'resource_id': resource.id,
'person_id': person.id,}) }}"
class="btn btn-sm btn-edit"
title="{{ 'Edit'|trans }}"></a>
</li>
<li>
<a href="{{ chill_path_add_return_path('chill_person_resource_delete', {'person_id': person.id,
'resource_id': resource.id}) }}"
class="btn btn-sm btn-delete"
title="{{ 'Delete'|trans }}"></a>
</li>
</ul>
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<p>{{ 'There are no available resources'|trans }}</p>
{% endif %}
<h1 style="margin-bottom: 2rem;">{{ 'Add a person resource'|trans }}</h1>
{% include "@ChillPerson/PersonResource/create.html.twig" %}
{% endblock %}

View File

@@ -0,0 +1,52 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Templating\Entity;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\Person\PersonResourceKind;
final class ResourceKindRender implements ChillEntityRenderInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function renderBox($entity, array $options): string
{
return
'<span class="resource">' .
$this->translatableStringHelper->localize(
$entity->getTitle()
) .
'</span>';
}
public function renderString($entity, array $options): string
{
$title = '';
if (null !== $entity->getTitle()) {
return $this->translatableStringHelper->localize($entity->getTitle());
}
return $title;
}
public function supports($entity, array $options): bool
{
return $entity instanceof PersonResourceKind;
}
}

View File

@@ -20,5 +20,6 @@ module.exports = function(encore, entries)
encore.addEntry('page_person', __dirname + '/Resources/public/page/person/index.js');
encore.addEntry('page_accompanying_course_index_person_locate', __dirname + '/Resources/public/page/accompanying_course_index/person_locate.js');
encore.addEntry('page_accompanying_course_index_masonry', __dirname + '/Resources/public/page/accompanying_course_index/masonry.js');
encore.addEntry('page_person_resource_showhide_input', __dirname + '/Resources/public/page/person_resource/showhide-input.js');
encore.addEntry('page_suggest_names', __dirname + '/Resources/public/page/person/suggest-names.js');
};

View File

@@ -55,6 +55,18 @@ chill_person_accompanying_period_re_open:
path: /{_locale}/person/{person_id}/accompanying-period/{period_id}/re-open
controller: Chill\PersonBundle\Controller\AccompanyingPeriodController::reOpenAction
chill_person_resource_list:
path: /{_locale}/person/{person_id}/resources/list
controller: Chill\PersonBundle\Controller\PersonResourceController::listAction
chill_person_resource_edit:
path: /{_locale}/person/{person_id}/resources/{resource_id}/edit
controller: Chill\PersonBundle\Controller\PersonResourceController::editAction
chill_person_resource_delete:
path: /{_locale}/person/{person_id}/resources/{resource_id}/delete
controller: Chill\PersonBundle\Controller\PersonResourceController::deleteAction
chill_person_address_list:
path: /{_locale}/person/{person_id}/address/list
controller: Chill\PersonBundle\Controller\PersonAddressController::listAction

View File

@@ -0,0 +1,54 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Creation of person resource and person resource kind.
*/
final class Version20220119155944 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('DROP SEQUENCE chill_person_resource_id_seq CASCADE');
$this->addSql('DROP SEQUENCE chill_person_resource_kind_id_seq CASCADE');
$this->addSql('DROP TABLE chill_person_resource');
$this->addSql('DROP TABLE chill_person_resource_kind');
}
public function getDescription(): string
{
return 'Creation of person resource and person resource kind';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE chill_person_resource_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE chill_person_resource_kind_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE chill_person_resource (id INT NOT NULL, person_id INT DEFAULT NULL, kind_id INT DEFAULT NULL, freeText TEXT DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, comment_comment TEXT DEFAULT NULL, comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, comment_userId INT DEFAULT NULL, personOwner_id INT NOT NULL, thirdParty_id INT DEFAULT NULL, createdBy_id INT NOT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_FA5B7D92D19C515B ON chill_person_resource (personOwner_id)');
$this->addSql('CREATE INDEX IDX_FA5B7D92217BBB47 ON chill_person_resource (person_id)');
$this->addSql('CREATE INDEX IDX_FA5B7D923EA5CAB0 ON chill_person_resource (thirdParty_id)');
$this->addSql('CREATE INDEX IDX_FA5B7D9230602CA9 ON chill_person_resource (kind_id)');
$this->addSql('CREATE INDEX IDX_FA5B7D923174800F ON chill_person_resource (createdBy_id)');
$this->addSql('CREATE INDEX IDX_FA5B7D9265FF1AEC ON chill_person_resource (updatedBy_id)');
$this->addSql('CREATE TABLE chill_person_resource_kind (id INT NOT NULL, title JSON NOT NULL, isActive BOOLEAN NOT NULL, PRIMARY KEY(id))');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D92D19C515B FOREIGN KEY (personOwner_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D92217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D923EA5CAB0 FOREIGN KEY (thirdParty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D9230602CA9 FOREIGN KEY (kind_id) REFERENCES chill_person_resource_kind (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D923174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_resource ADD CONSTRAINT FK_FA5B7D9265FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
}

View File

@@ -223,6 +223,23 @@ Are you sure you want to remove the accompanying period "%id%" ?: Êtes-vous s
The accompanying course has been successfully removed.: La période d'accompagnement a été supprimée.
Concerned scopes: Services concernés
# person resource
person_resources_menu: "Ressources"
Person resources: "Ressources de la personne"
Add a person resource: "Ajouter une ressource"
edit resource: "Modifier ressource"
Remove resource: "Supprimer ressource"
Are you sure you want to remove the resource for "%name%" ?: Étes-vous sûr de vouloir supprimer cette ressource de %name%?
The resource has been successfully removed.: "La ressource a été supprimée."
List of resources: "Liste des ressources"
There are no available resources: "Il y aucun ressource"
no comment found: "Aucun commentaire"
Select a type: "Choisissez un type"
Select a person: "Choisissez un usager"
Select a thirdparty: "Choisissez un tiers"
# pickAPersonType
Pick a person: Choisir une personne