mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge branch '139_demandeur' into 'master'
139 Demandeur See merge request Chill-Projet/chill-bundles!43
This commit is contained in:
@@ -5,13 +5,19 @@ namespace Chill\PersonBundle\Controller;
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
|
||||
class AccompanyingCourseApiController extends ApiController
|
||||
{
|
||||
@@ -19,10 +25,37 @@ class AccompanyingCourseApiController extends ApiController
|
||||
|
||||
protected ValidatorInterface $validator;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher, $validator)
|
||||
{
|
||||
private Registry $registry;
|
||||
|
||||
public function __construct(
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
ValidatorInterface $validator,
|
||||
Registry $registry
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->validator = $validator;
|
||||
$this->registry = $registry;
|
||||
}
|
||||
|
||||
public function confirmApi($id, Request $request, $_format): Response
|
||||
{
|
||||
/** @var AccompanyingPeriod $accompanyingPeriod */
|
||||
$accompanyingPeriod = $this->getEntity('participation', $id, $request);
|
||||
|
||||
$this->checkACL('confirm', $request, $_format, $accompanyingPeriod);
|
||||
$workflow = $this->registry->get($accompanyingPeriod);
|
||||
|
||||
if (FALSE === $workflow->can($accompanyingPeriod, 'confirm')) {
|
||||
throw new BadRequestException('It is not possible to confirm this period');
|
||||
}
|
||||
|
||||
$workflow->apply($accompanyingPeriod, 'confirm');
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->json($accompanyingPeriod, Response::HTTP_OK, [], [
|
||||
'groups' => [ 'read' ]
|
||||
]);
|
||||
}
|
||||
|
||||
public function participationApi($id, Request $request, $_format)
|
||||
@@ -46,7 +79,6 @@ class AccompanyingCourseApiController extends ApiController
|
||||
break;
|
||||
case Request::METHOD_DELETE:
|
||||
$participation = $accompanyingPeriod->removePerson($person);
|
||||
$participation->setEndDate(new \DateTimeImmutable('now'));
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException("This method is not supported");
|
||||
@@ -56,12 +88,76 @@ class AccompanyingCourseApiController extends ApiController
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
// only format accepted
|
||||
return $this->json($errors);
|
||||
return $this->json($errors, 422);
|
||||
}
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->json($participation);
|
||||
return $this->json($participation, 200, [], ['groups' => [ 'read' ]]);
|
||||
}
|
||||
|
||||
public function resourceApi($id, Request $request, string $_format): Response
|
||||
{
|
||||
return $this->addRemoveSomething('resource', $id, $request, $_format, 'resource', Resource::class);
|
||||
}
|
||||
|
||||
public function scopeApi($id, Request $request, string $_format): Response
|
||||
{
|
||||
return $this->addRemoveSomething('scope', $id, $request, $_format, 'scope', Scope::class, [ 'groups' => [ 'read' ] ]);
|
||||
}
|
||||
|
||||
public function commentApi($id, Request $request, string $_format): Response
|
||||
{
|
||||
return $this->addRemoveSomething('comment', $id, $request, $_format, 'comment', Comment::class);
|
||||
}
|
||||
|
||||
public function socialIssueApi($id, Request $request, string $_format): Response
|
||||
{
|
||||
return $this->addRemoveSomething('socialissue', $id, $request, $_format, 'socialIssue', SocialIssue::class, [ 'groups' => [ 'read' ] ]);
|
||||
}
|
||||
|
||||
public function requestorApi($id, Request $request, string $_format): Response
|
||||
{
|
||||
/** @var AccompanyingPeriod $accompanyingPeriod */
|
||||
$action = 'requestor';
|
||||
$accompanyingPeriod = $this->getEntity($action, $id, $request);
|
||||
// a requestor may be a person or a thirdParty
|
||||
|
||||
$this->checkACL($action, $request, $_format, $accompanyingPeriod);
|
||||
$this->onPostCheckACL($action, $request, $_format, $accompanyingPeriod);
|
||||
|
||||
if (Request::METHOD_DELETE === $request->getMethod()) {
|
||||
$accompanyingPeriod->setRequestor(NULL);
|
||||
} elseif (Request::METHOD_POST === $request->getMethod()) {
|
||||
$requestor = null;
|
||||
$exceptions = [];
|
||||
foreach ([Person::class, ThirdParty::class] as $class) {
|
||||
try {
|
||||
$requestor = $this->getSerializer()
|
||||
->deserialize($request->getContent(), $class, $_format, []);
|
||||
} catch (RuntimeException $e) {
|
||||
$exceptions[] = $e;
|
||||
}
|
||||
}
|
||||
if ($requestor === null) {
|
||||
throw new BadRequestException('Could not find any person or requestor', 0, $exceptions[0]);
|
||||
}
|
||||
|
||||
$accompanyingPeriod->setRequestor($requestor);
|
||||
} else {
|
||||
throw new BadRequestException('method not supported');
|
||||
}
|
||||
|
||||
$errors = $this->validator->validate($accompanyingPeriod);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
// only format accepted
|
||||
return $this->json($errors, 422);
|
||||
}
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->json($accompanyingPeriod->getRequestor(), 200, [], ['groups' => [ 'read']]);
|
||||
}
|
||||
|
||||
protected function onPostCheckACL(string $action, Request $request, string $_format, $entity): ?Response
|
||||
|
@@ -6,6 +6,7 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -42,6 +43,41 @@ class AccompanyingCourseController extends Controller
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/person/parcours/new", name="chill_person_accompanying_course_new")
|
||||
*/
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
$period = new AccompanyingPeriod();
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
if ($request->query->has('person_id')) {
|
||||
$personIds = $request->query->get('person_id');
|
||||
|
||||
if (FALSE === \is_array($personIds)) {
|
||||
throw new BadRequestException("person_id parameter should be an array");
|
||||
}
|
||||
|
||||
foreach ($personIds as $personId) {
|
||||
$person = $em->getRepository(Person::class)->find($personId);
|
||||
if (NULL !== $person) {
|
||||
$period->addPerson($person);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $period);
|
||||
|
||||
$em->persist($period);
|
||||
$em->flush();
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_course_show', [
|
||||
'accompanying_period_id' => $period->getId()
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Homepage of Accompanying Course section
|
||||
*
|
||||
@@ -86,78 +122,4 @@ class AccompanyingCourseController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get API Data for showing endpoint
|
||||
*
|
||||
* @Route(
|
||||
* "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/show.{_format}",
|
||||
* name="chill_person_accompanying_course_api_show"
|
||||
* )
|
||||
* @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"})
|
||||
*/
|
||||
public function showAPI(AccompanyingPeriod $accompanyingCourse, $_format): Response
|
||||
{
|
||||
// TODO check ACL on AccompanyingPeriod
|
||||
|
||||
$this->dispatcher->dispatch(
|
||||
AccompanyingPeriodPrivacyEvent::ACCOMPANYING_PERIOD_PRIVACY_EVENT,
|
||||
new AccompanyingPeriodPrivacyEvent($accompanyingCourse, [
|
||||
'action' => 'showApi'
|
||||
])
|
||||
);
|
||||
|
||||
switch ($_format) {
|
||||
case 'json':
|
||||
return $this->json($accompanyingCourse);
|
||||
default:
|
||||
throw new BadRequestException('Unsupported format');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get API Data for showing endpoint
|
||||
*
|
||||
* @Route(
|
||||
* "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/participation.{_format}",
|
||||
* name="chill_person_accompanying_course_api_add_participation",
|
||||
* methods={"POST","DELETE"},
|
||||
* format="json",
|
||||
* requirements={
|
||||
* "_format": "json",
|
||||
* }
|
||||
* )
|
||||
* @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"})
|
||||
*/
|
||||
public function participationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response
|
||||
{
|
||||
switch ($_format) {
|
||||
case 'json':
|
||||
$person = $this->serializer->deserialize($request->getContent(), Person::class, $_format, [
|
||||
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException('Unsupported format');
|
||||
}
|
||||
|
||||
if (NULL === $person) {
|
||||
throw new BadRequestException('person id not found');
|
||||
}
|
||||
|
||||
// TODO add acl
|
||||
$participation = ($request->getMethod() === 'POST') ?
|
||||
$accompanyingCourse->addPerson($person) : $accompanyingCourse->removePerson($person);
|
||||
|
||||
$errors = $this->validator->validate($accompanyingCourse);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
// only format accepted
|
||||
return $this->json($errors);
|
||||
}
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->json($participation);
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
@@ -166,6 +165,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
$this->prependHomepageWidget($container);
|
||||
$this->prependDoctrineDQL($container);
|
||||
$this->prependCruds($container);
|
||||
$this->prependWorkflows($container);
|
||||
|
||||
//add person_fields parameter as global
|
||||
$chillPersonConfig = $container->getExtensionConfig($this->getAlias());
|
||||
@@ -195,6 +195,39 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
));
|
||||
}
|
||||
|
||||
protected function prependWorkflows(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('framework', [
|
||||
'workflows' => [
|
||||
'accompanying_period_lifecycle' => [
|
||||
'type' => 'state_machine',
|
||||
'audit_trail' => [
|
||||
'enabled' => true
|
||||
],
|
||||
'marking_store' => [
|
||||
'type' => 'method',
|
||||
'property' => 'step',
|
||||
],
|
||||
'supports' => [
|
||||
'Chill\PersonBundle\Entity\AccompanyingPeriod'
|
||||
],
|
||||
'initial_marking' => 'DRAFT',
|
||||
'places' => [
|
||||
'DRAFT',
|
||||
'CONFIRMED',
|
||||
],
|
||||
'transitions' => [
|
||||
'confirm' => [
|
||||
'from' => 'DRAFT',
|
||||
'to' => 'CONFIRMED'
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a widget "add a person" on the homepage, automatically
|
||||
*
|
||||
@@ -321,8 +354,15 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseApiController::class,
|
||||
'actions' => [
|
||||
'_entity' => [
|
||||
'roles' => [
|
||||
Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
'roles' => [
|
||||
Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_PATCH => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_PUT => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
],
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_PUT => true,
|
||||
Request::METHOD_PATCH => true,
|
||||
]
|
||||
],
|
||||
'participation' => [
|
||||
@@ -336,8 +376,79 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
]
|
||||
],
|
||||
'resource' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
],
|
||||
'comment' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
],
|
||||
'requestor' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
],
|
||||
'scope' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
],
|
||||
'socialissue' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'controller_action' => 'socialIssueApi',
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
|
||||
]
|
||||
],
|
||||
|
||||
'confirm' => [
|
||||
'methods' => [
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_HEAD => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
@@ -360,7 +471,28 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\SocialWork\SocialIssue::class,
|
||||
'name' => 'social_work_social_issue',
|
||||
'base_path' => '/api/1.0/person/social-work/social-issue',
|
||||
// 'controller' => \Chill\PersonBundle\Controller\OpeningApiController::class,
|
||||
'base_role' => 'ROLE_USER',
|
||||
'actions' => [
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true
|
||||
],
|
||||
],
|
||||
'_entity' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
@@ -22,25 +22,34 @@
|
||||
|
||||
namespace Chill\PersonBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
|
||||
/**
|
||||
* AccompanyingPeriod Class
|
||||
*
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="chill_person_accompanying_period")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "accompanying_period"=AccompanyingPeriod::class
|
||||
* })
|
||||
*/
|
||||
class AccompanyingPeriod
|
||||
class AccompanyingPeriod implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
/**
|
||||
* Mark an accompanying period as "occasional"
|
||||
@@ -80,6 +89,7 @@ class AccompanyingPeriod
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
@@ -87,6 +97,7 @@ class AccompanyingPeriod
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="date")
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $openingDate;
|
||||
|
||||
@@ -94,6 +105,7 @@ class AccompanyingPeriod
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="date", nullable=true)
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $closingDate = null;
|
||||
|
||||
@@ -101,6 +113,7 @@ class AccompanyingPeriod
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text")
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $remark = '';
|
||||
|
||||
@@ -108,17 +121,28 @@ class AccompanyingPeriod
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Comment",
|
||||
* mappedBy="accompanyingPeriod"
|
||||
* mappedBy="accompanyingPeriod",
|
||||
* cascade={"persist", "remove"},
|
||||
* orphanRemoval=true
|
||||
* )
|
||||
*/
|
||||
private $comments;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity=Comment::class
|
||||
* )
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private ?Comment $initialComment = null;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class,
|
||||
* mappedBy="accompanyingPeriod",
|
||||
* cascade={"persist", "refresh", "remove", "merge", "detach"})
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $participations;
|
||||
|
||||
@@ -128,36 +152,42 @@ class AccompanyingPeriod
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $closingMotive = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $createdBy;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=32, nullable=true)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $step = self::STEP_DRAFT;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Origin::class)
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $origin;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $intensity;
|
||||
|
||||
@@ -172,6 +202,7 @@ class AccompanyingPeriod
|
||||
* joinColumns={@ORM\JoinColumn(name="accompanying_period_id", referencedColumnName="id")},
|
||||
* inverseJoinColumns={@ORM\JoinColumn(name="scope_id", referencedColumnName="id")}
|
||||
* )
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $scopes;
|
||||
|
||||
@@ -189,19 +220,22 @@ class AccompanyingPeriod
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @ORM\Column(type="boolean")
|
||||
* @ORM\Column(type="boolean", options={"default": false} )
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $requestorAnonymous = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @ORM\Column(type="boolean")
|
||||
* @ORM\Column(type="boolean", options={"default": false} )
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $emergency = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @ORM\Column(type="boolean")
|
||||
* @ORM\Column(type="boolean", options={"default": false} )
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $confidential = false;
|
||||
|
||||
@@ -210,21 +244,54 @@ class AccompanyingPeriod
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\Resource",
|
||||
* mappedBy="accompanyingPeriod"
|
||||
* mappedBy="accompanyingPeriod",
|
||||
* cascade={"persist", "remove"},
|
||||
* orphanRemoval=true
|
||||
* )
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $resources;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity=SocialIssue::class
|
||||
* )
|
||||
* @ORM\JoinTable(
|
||||
* name="chill_person_accompanying_period_social_issues"
|
||||
* )
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private Collection $socialIssues;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true, options={"default": NULL})
|
||||
*/
|
||||
private \DateTimeInterface $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity=User::class
|
||||
* )
|
||||
*/
|
||||
private User $updatedBy;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true, options={"default": NULL})
|
||||
*/
|
||||
private \DateTimeInterface $updatedAt;
|
||||
|
||||
/**
|
||||
* AccompanyingPeriod constructor.
|
||||
*
|
||||
* @param \DateTime $dateOpening
|
||||
* @uses AccompanyingPeriod::setClosingDate()
|
||||
*/
|
||||
public function __construct(\DateTime $dateOpening) {
|
||||
$this->setOpeningDate($dateOpening);
|
||||
public function __construct(\DateTime $dateOpening = null) {
|
||||
$this->setOpeningDate($dateOpening ?? new \DateTime('now'));
|
||||
$this->participations = new ArrayCollection();
|
||||
$this->scopes = new ArrayCollection();
|
||||
$this->socialIssues = new ArrayCollection();
|
||||
$this->comments = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,23 +385,55 @@ class AccompanyingPeriod
|
||||
return $this->remark;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
public function getComments(): Collection
|
||||
{
|
||||
return $this->comments;
|
||||
return $this->comments->filter(function (Comment $c) {
|
||||
return $c !== $this->initialComment;
|
||||
});
|
||||
}
|
||||
|
||||
public function addComment(Comment $comment): self
|
||||
{
|
||||
$this->comments[] = $comment;
|
||||
$comment->setAccompanyingPeriod($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeComment(Comment $comment): void
|
||||
{
|
||||
$comment->setAccompanyingPeriod(null);
|
||||
$this->comments->removeElement($comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Groups({"write"})
|
||||
*/
|
||||
public function setInitialComment(?Comment $comment = null): self
|
||||
{
|
||||
if (NULL !== $this->initialComment) {
|
||||
$this->removeComment($this->initialComment);
|
||||
}
|
||||
if ($comment instanceof Comment) {
|
||||
$this->addComment($comment);
|
||||
}
|
||||
|
||||
$this->initialComment = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
public function getInitialComment(): ?Comment
|
||||
{
|
||||
return $this->initialComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Participations Collection
|
||||
*/
|
||||
@@ -515,9 +614,9 @@ class AccompanyingPeriod
|
||||
return $this->requestorPerson;
|
||||
}
|
||||
|
||||
public function setRequestorPerson(Person $requestorPerson): self
|
||||
private function setRequestorPerson(Person $requestorPerson = null): self
|
||||
{
|
||||
$this->requestorPerson = ($this->requestorThirdParty === null) ? $requestorPerson : null;
|
||||
$this->requestorPerson = $requestorPerson;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -527,21 +626,53 @@ class AccompanyingPeriod
|
||||
return $this->requestorThirdParty;
|
||||
}
|
||||
|
||||
public function setRequestorThirdParty(ThirdParty $requestorThirdParty): self
|
||||
private function setRequestorThirdParty(ThirdParty $requestorThirdParty = null): self
|
||||
{
|
||||
$this->requestorThirdParty = ($this->requestorPerson === null) ? $requestorThirdParty : null;
|
||||
$this->requestorThirdParty = $requestorThirdParty;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Person|ThirdParty
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
public function getRequestor()
|
||||
{
|
||||
return $this->requestorPerson ?? $this->requestorThirdParty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a requestor
|
||||
*
|
||||
* The requestor is either an instance of ThirdParty, or an
|
||||
* instance of Person
|
||||
*
|
||||
* @param $requestor Person|ThirdParty
|
||||
* @return self
|
||||
* @throw UnexpectedValueException if the requestor is not a Person or ThirdParty
|
||||
* @Groups({"write"})
|
||||
*/
|
||||
public function setRequestor($requestor): self
|
||||
{
|
||||
if ($requestor instanceof Person) {
|
||||
$this->setRequestorThirdParty(NULL);
|
||||
$this->setRequestorPerson($requestor);
|
||||
} elseif ($requestor instanceof ThirdParty) {
|
||||
$this->setRequestorThirdParty($requestor);
|
||||
$this->setRequestorPerson(NULL);
|
||||
} elseif (NULL === $requestor) {
|
||||
$this->setRequestorPerson(NULL);
|
||||
$this->setRequestorThirdParty(NULL);
|
||||
} else {
|
||||
throw new \UnexpectedValueException("requestor is not an instance of Person or ThirdParty");
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function isRequestorAnonymous(): bool
|
||||
{
|
||||
return $this->requestorAnonymous;
|
||||
@@ -638,6 +769,7 @@ class AccompanyingPeriod
|
||||
|
||||
public function addResource(Resource $resource): self
|
||||
{
|
||||
$resource->setAccompanyingPeriod($this);
|
||||
$this->resources[] = $resource;
|
||||
|
||||
return $this;
|
||||
@@ -645,9 +777,27 @@ class AccompanyingPeriod
|
||||
|
||||
public function removeResource(Resource $resource): void
|
||||
{
|
||||
$resource->setAccompanyingPeriod(null);
|
||||
$this->resources->removeElement($resource);
|
||||
}
|
||||
|
||||
public function getSocialIssues(): Collection
|
||||
{
|
||||
return $this->socialIssues;
|
||||
}
|
||||
|
||||
public function addSocialIssue(SocialIssue $socialIssue): self
|
||||
{
|
||||
$this->socialIssues[] = $socialIssue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeSocialIssue(SocialIssue $socialIssue): void
|
||||
{
|
||||
$this->socialIssues->removeElement($socialIssue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all persons which are participating to this course
|
||||
*/
|
||||
@@ -659,4 +809,25 @@ class AccompanyingPeriod
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeInterface $datetime): self
|
||||
{
|
||||
$this->createdAt = $datetime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUpdatedBy(User $user): self
|
||||
{
|
||||
$this->updatedBy = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeInterface $datetime): self
|
||||
{
|
||||
$this->updatedAt = $datetime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -25,17 +25,25 @@ namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="chill_person_accompanying_period_comment")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "accompanying_period_comment"=Comment::class
|
||||
* })
|
||||
*/
|
||||
class Comment
|
||||
class Comment implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
@@ -50,27 +58,32 @@ class Comment
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $creator;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $updatedAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $updatedBy;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
private $content;
|
||||
|
||||
@@ -103,6 +116,11 @@ class Comment
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCreatedBy(User $user): self
|
||||
{
|
||||
return $this->setCreator($user);
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->createdAt;
|
||||
@@ -132,7 +150,7 @@ class Comment
|
||||
return $this->updatedBy;
|
||||
}
|
||||
|
||||
public function setUpdatedBy(?User $updatedBy): self
|
||||
public function setUpdatedBy(User $updatedBy): self
|
||||
{
|
||||
$this->updatedBy = $updatedBy;
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
@@ -34,16 +35,19 @@ class Origin
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $label;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $noActiveAfter;
|
||||
|
||||
|
@@ -25,12 +25,18 @@ namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\ResourceRepository;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Entity(repositoryClass=ResourceRepository::class)
|
||||
* @ORM\Table(name="chill_person_accompanying_period_resource")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "accompanying_period_resource"=Resource::class
|
||||
* })
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
@@ -38,6 +44,7 @@ class Resource
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
@@ -90,7 +97,7 @@ class Resource
|
||||
return $this->thirdParty;
|
||||
}
|
||||
|
||||
public function setThirdParty(?ThirdParty $thirdParty): self
|
||||
private function setThirdParty(?ThirdParty $thirdParty): self
|
||||
{
|
||||
$this->thirdParty = $thirdParty;
|
||||
|
||||
@@ -102,7 +109,7 @@ class Resource
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function setPerson(?Person $person): self
|
||||
private function setPerson(?Person $person): self
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
@@ -120,9 +127,35 @@ class Resource
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $resource Person|ThirdParty
|
||||
*/
|
||||
public function setResource($resource): self
|
||||
{
|
||||
if ($resource instanceof ThirdParty) {
|
||||
$this->setThirdParty($resource);
|
||||
$this->setPerson(NULL);
|
||||
} elseif ($resource instanceof Person) {
|
||||
$this->setPerson($resource);
|
||||
$this->setThirdParty(NULL);
|
||||
} elseif (NULL === $resource) {
|
||||
$this->setPerson(NULL);
|
||||
$this->setThirdParty(NULL);
|
||||
} else {
|
||||
throw new \UnexpectedValueException(sprintf("the resource ".
|
||||
"should be an instance of %s or %s", Person::class,
|
||||
ThirdParty::class));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Person|ThirdParty
|
||||
* @return ThirdParty|Person
|
||||
* @Groups({"read", "write"})
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
|
@@ -25,6 +25,8 @@ namespace Chill\PersonBundle\Entity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
|
||||
/**
|
||||
* AccompanyingPeriodParticipation Class
|
||||
@@ -32,6 +34,9 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
* @package Chill\PersonBundle\Entity
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="chill_person_accompanying_period_participation")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "accompanying_period_participation"=AccompanyingPeriodParticipation::class
|
||||
* })
|
||||
*/
|
||||
class AccompanyingPeriodParticipation
|
||||
{
|
||||
@@ -39,12 +44,14 @@ class AccompanyingPeriodParticipation
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations")
|
||||
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $person;
|
||||
|
||||
@@ -56,11 +63,13 @@ class AccompanyingPeriodParticipation
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date", nullable=false)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $startDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date", nullable=true)
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $endDate = null;
|
||||
|
||||
|
@@ -34,6 +34,7 @@ use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
|
||||
/**
|
||||
* Person Class
|
||||
@@ -45,6 +46,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
* columns={"firstName", "lastName"}
|
||||
* )})
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "person"=Person::class
|
||||
* })
|
||||
*/
|
||||
class Person implements HasCenterInterface
|
||||
{
|
||||
|
@@ -4,10 +4,15 @@ namespace Chill\PersonBundle\Entity\SocialWork;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="chill_person_social_issue")
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "social_issue"=SocialIssue::class
|
||||
* })
|
||||
*/
|
||||
class SocialIssue
|
||||
{
|
||||
@@ -35,6 +40,7 @@ class SocialIssue
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private $title = [];
|
||||
|
||||
@@ -59,6 +65,11 @@ class SocialIssue
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
public function setParent(?self $parent): self
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Chill\PersonBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -32,24 +33,31 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
||||
{
|
||||
$period = $parameters['accompanyingCourse'];
|
||||
|
||||
$menu->addChild($this->translator->trans('Resume Accompanying Course'), [
|
||||
'route' => 'chill_person_accompanying_course_index',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $parameters['accompanyingCourse']->getId()
|
||||
'accompanying_period_id' => $period->getId()
|
||||
]])
|
||||
->setExtras(['order' => 10]);
|
||||
|
||||
$menu->addChild($this->translator->trans('Edit Accompanying Course'), [
|
||||
'route' => 'chill_person_accompanying_course_show',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $parameters['accompanyingCourse']->getId()
|
||||
'accompanying_period_id' => $period->getId()
|
||||
]])
|
||||
->setExtras(['order' => 20]);
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT === $period->getStep()) {
|
||||
// no more menu items if the period is draft
|
||||
return;
|
||||
}
|
||||
|
||||
$menu->addChild($this->translator->trans('Accompanying Course Details'), [
|
||||
'route' => 'chill_person_accompanying_course_history',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $parameters['accompanyingCourse']->getId()
|
||||
'accompanying_period_id' => $period->getId()
|
||||
]])
|
||||
->setExtras(['order' => 30]);
|
||||
}
|
||||
|
@@ -71,6 +71,14 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
}
|
||||
|
||||
$menu->addChild($this->translator->trans('Create an accompanying course'), [
|
||||
'route' => 'chill_person_accompanying_course_new'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 11,
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -23,8 +23,9 @@
|
||||
namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Resource|null find($id, $lockMode = null, $lockVersion = null)
|
||||
@@ -32,12 +33,12 @@ use Doctrine\ORM\EntityRepository;
|
||||
* @method Resource[] findAll()
|
||||
* @method Resource[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
final class ResourceRepository
|
||||
final class ResourceRepository extends ServiceEntityRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(Resource::class);
|
||||
parent::__construct($registry, Resource::class);
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,94 @@
|
||||
<template>
|
||||
<accompanying-course></accompanying-course>
|
||||
<banner></banner>
|
||||
|
||||
<h1 v-if="accompanyingCourse.step === 'DRAFT'">{{ $t('course.title.draft') }}</h1>
|
||||
<h1 v-else>{{ $t('course.title.active') }}</h1>
|
||||
|
||||
<persons-associated></persons-associated>
|
||||
<requestor></requestor>
|
||||
<social-issue></social-issue>
|
||||
<referrer></referrer>
|
||||
<resources></resources>
|
||||
<comment v-if="accompanyingCourse.step === 'DRAFT'"></comment>
|
||||
<confirm v-if="accompanyingCourse.step === 'DRAFT'"></confirm>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
import AccompanyingCourse from './components/AccompanyingCourse.vue';
|
||||
import Banner from './components/Banner.vue';
|
||||
import PersonsAssociated from './components/PersonsAssociated.vue';
|
||||
import Requestor from './components/Requestor.vue';
|
||||
import SocialIssue from './components/SocialIssue.vue';
|
||||
import Referrer from './components/Referrer.vue';
|
||||
import Resources from './components/Resources.vue';
|
||||
import Comment from './components/Comment.vue';
|
||||
import Confirm from './components/Confirm.vue';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
AccompanyingCourse,
|
||||
Banner,
|
||||
PersonsAssociated,
|
||||
Requestor
|
||||
Requestor,
|
||||
SocialIssue,
|
||||
Referrer,
|
||||
Resources,
|
||||
Comment,
|
||||
Confirm,
|
||||
},
|
||||
computed: mapState([
|
||||
'accompanyingCourse'
|
||||
])
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
h1 {
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
div.vue-component {
|
||||
h2 {
|
||||
margin-left: 0.7em;
|
||||
position: relative;
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: "\f192";
|
||||
font-family: "ForkAwesome";
|
||||
color: #718596ab;
|
||||
left: -28px;
|
||||
top: 4px;
|
||||
}
|
||||
a[name^="section"] {
|
||||
position: absolute;
|
||||
top: -2em;
|
||||
}
|
||||
}
|
||||
padding: 0.8em 0em;
|
||||
margin: 2em 0;
|
||||
border: 1px dotted #718596ab;
|
||||
border-radius: 5px;
|
||||
border-left: 1px dotted #718596ab;
|
||||
border-right: 1px dotted #718596ab;
|
||||
/*
|
||||
position: relative;
|
||||
&:before {
|
||||
content: "vuejs component";
|
||||
position: absolute;
|
||||
left: 1.5em;
|
||||
top: -0.9em;
|
||||
background-color: white;
|
||||
color: grey;
|
||||
padding: 0 0.3em;
|
||||
}
|
||||
*/
|
||||
dd {
|
||||
margin-left: 1em;
|
||||
}
|
||||
& > div {
|
||||
margin: 1em 3em 0;
|
||||
}
|
||||
table {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,18 +1,11 @@
|
||||
const
|
||||
locale = 'fr',
|
||||
format = 'json'
|
||||
, accompanying_period_id = window.accompanyingCourseId //tmp
|
||||
;
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_accompanying_course_api_show
|
||||
* method GET, get AccompanyingCourse Object
|
||||
* Endpoint v.2 chill_api_single_accompanying_course__entity
|
||||
* method GET/HEAD, get AccompanyingCourse Instance
|
||||
*
|
||||
* @accompanying_period_id___ integer
|
||||
* @TODO var is not used but necessary in method signature
|
||||
* @id integer - id of accompanyingCourse
|
||||
*/
|
||||
let getAccompanyingCourse = (accompanying_period_id___) => { //tmp
|
||||
const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/show.${format}`;
|
||||
const getAccompanyingCourse = (id) => {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
@@ -21,21 +14,131 @@ let getAccompanyingCourse = (accompanying_period_id___) => { //tmp
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_accompanying_course_api_add_participation,
|
||||
* Endpoint v.2 chill_api_single_accompanying_course__entity
|
||||
* method PATCH, patch AccompanyingCourse Instance
|
||||
*
|
||||
* @id integer - id of accompanyingCourse
|
||||
* @body Object - dictionary with changes to post
|
||||
*/
|
||||
const patchAccompanyingCourse = (id, body) => {
|
||||
console.log('body', body);
|
||||
const url = `/api/1.0/person/accompanying-course/${id}.json`;
|
||||
return fetch(url, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint to change 'DRAFT' step to 'CONFIRMED'
|
||||
*/
|
||||
const confirmAccompanyingCourse = (id) => {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/confirm.json`
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint
|
||||
*/
|
||||
const getSocialIssues = () => {
|
||||
const url = `/api/1.0/person/social-work/social-issue.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint v.2 chill_api_single_accompanying_course_participation,
|
||||
* method POST/DELETE, add/close a participation to the accompanyingCourse
|
||||
*
|
||||
* @accompanying_period_id integer - id of accompanyingCourse
|
||||
* @person_id integer - id of person
|
||||
* @method string - POST or DELETE
|
||||
* @id integer - id of accompanyingCourse
|
||||
* @payload integer - id of person
|
||||
* @method string - POST or DELETE
|
||||
*/
|
||||
let postParticipation = (accompanying_period_id, person_id, method) => {
|
||||
const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/participation.${format}`
|
||||
const postParticipation = (id, payload, method) => {
|
||||
const body = { type: payload.type, id: payload.id };
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/participation.json`;
|
||||
return fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify({id: person_id})
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint v.2 chill_api_single_accompanying_course_requestor,
|
||||
* method POST/DELETE, add/close a requestor to the accompanyingCourse
|
||||
*
|
||||
* @id integer - id of accompanyingCourse
|
||||
* @payload object of type person|thirdparty
|
||||
* @method string - POST or DELETE
|
||||
*/
|
||||
const postRequestor = (id, payload, method) => {
|
||||
//console.log('payload', payload);
|
||||
const body = (payload)? { type: payload.type, id: payload.id } : {};
|
||||
console.log('body', body);
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/requestor.json`;
|
||||
return fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint v.2 chill_api_single_accompanying_course_resource,
|
||||
* method POST/DELETE, add/remove a resource to the accompanyingCourse
|
||||
*
|
||||
* @id integer - id of accompanyingCourse
|
||||
* @payload object of type person|thirdparty
|
||||
* @method string - POST or DELETE
|
||||
*/
|
||||
const postResource = (id, payload, method) => {
|
||||
//console.log('payload', payload);
|
||||
const body = { type: "accompanying_period_resource" };
|
||||
switch (method) {
|
||||
case 'DELETE':
|
||||
body['id'] = payload.id;
|
||||
break;
|
||||
default:
|
||||
body['resource'] = { type: payload.type, id: payload.id };
|
||||
}
|
||||
console.log('body', body);
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/resource.json`;
|
||||
return fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
@@ -44,6 +147,11 @@ let postParticipation = (accompanying_period_id, person_id, method) => {
|
||||
};
|
||||
|
||||
export {
|
||||
getAccompanyingCourse,
|
||||
postParticipation
|
||||
getAccompanyingCourse,
|
||||
patchAccompanyingCourse,
|
||||
confirmAccompanyingCourse,
|
||||
getSocialIssues,
|
||||
postParticipation,
|
||||
postRequestor,
|
||||
postResource,
|
||||
};
|
||||
|
@@ -1,28 +0,0 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('course.title') }}</h3>
|
||||
<dl>
|
||||
<dt>{{ $t('course.id') }}</dt>
|
||||
<dd>{{ accompanyingCourse.id }}</dd>
|
||||
<dt>{{ $t('course.opening_date') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.openingDate.datetime, 'short') }}</dd>
|
||||
<dt>{{ $t('course.closing_date') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.closingDate.datetime, 'short') }}</dd>
|
||||
<dt>{{ $t('course.remark') }}</dt>
|
||||
<dd>{{ accompanyingCourse.remark }}</dd>
|
||||
<dt>{{ $t('course.closing_motive') }}</dt>
|
||||
<dd>{{ accompanyingCourse.closing_motive }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AccompanyingCourse',
|
||||
computed: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
|
||||
<div class="vue-component" style="display: none;">
|
||||
<dl>
|
||||
<dt>{{ $t('course.id') }}</dt>
|
||||
<dd>{{ accompanyingCourse.id }}</dd>
|
||||
</dl>
|
||||
<dl v-if="accompanyingCourse.closingDate">
|
||||
<dt>{{ $t('course.closing_date') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.closingDate.datetime, 'short') }}</dd>
|
||||
|
||||
<dt>{{ $t('course.closing_motive') }}</dt>
|
||||
<dd v-if="accompanyingCourse.closingMotive">{{ accompanyingCourse.closingMotive.name.fr }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<teleport to="#header-accompanying_course-name #banner-flags">
|
||||
<toggle-flags></toggle-flags>
|
||||
</teleport>
|
||||
|
||||
<teleport to="#header-accompanying_course-name #banner-status">
|
||||
<div v-if="accompanyingCourse.step === 'DRAFT'">
|
||||
<span class="badge badge-secondary">
|
||||
{{ $t('course.step.draft') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<span class="badge badge-primary">
|
||||
{{ $t('course.step.active') }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
<i>{{ $t('course.open_at') }}{{ $d(accompanyingCourse.openingDate.datetime, 'text') }}</i>
|
||||
</span>
|
||||
<br>
|
||||
<span v-if="accompanyingCourse.user">
|
||||
{{ $t('course.by') }}<b>{{ accompanyingCourse.user.username }}</b>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</teleport>
|
||||
|
||||
<teleport to="#header-accompanying_course-details #banner-social-issues">
|
||||
<div class="grid-4">{{ $t('social_issue.title') }}</div>
|
||||
<div class="grid-4">_</div>
|
||||
<div class="grid-4">_</div>
|
||||
</teleport>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ToggleFlags from './ToggleFlags';
|
||||
|
||||
export default {
|
||||
name: 'Banner',
|
||||
components: {
|
||||
ToggleFlags
|
||||
},
|
||||
computed: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
div#banner-flags,
|
||||
div#banner-status {
|
||||
margin: 1.5em 0;
|
||||
div {
|
||||
text-align: right;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
.badge {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
div#banner-status {
|
||||
span.badge {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h2><a name="section-60"></a>{{ $t('comment.title') }}</h2>
|
||||
|
||||
<!--div class="error flash_message" v-if="errors.length > 0">
|
||||
{{ errors[0] }}
|
||||
TODO fix errors flashbag for app component
|
||||
</div-->
|
||||
|
||||
<div>
|
||||
<div v-if="initialComment">
|
||||
créé par {{ initialComment.creator.text }}
|
||||
le {{ $d(initialComment.createdAt.datetime, 'long') }}
|
||||
<div v-if="initialComment.updatedAt.datetime !== initialComment.createdAt.datetime">
|
||||
modifié par {{ initialComment.updatedBy.text }}
|
||||
le {{ $d(initialComment.updatedAt.datetime, 'long') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="submitform">
|
||||
<label for="content">{{ $t('comment.label') }}</label>
|
||||
<textarea
|
||||
name="content"
|
||||
v-bind:placeholder="$t('comment.content')"
|
||||
rows="8"
|
||||
cols="80"
|
||||
ckeditor="ckeditor"
|
||||
v-model="content">
|
||||
</textarea>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="sc-button bt-save">{{ $t('action.save') }}</button>
|
||||
</li>
|
||||
<li v-if="initialComment !== null">
|
||||
<a class="sc-button bt-delete"
|
||||
@click="removeComment">
|
||||
{{ $t('action.delete') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Comment",
|
||||
data() {
|
||||
return {
|
||||
formdata: {
|
||||
type: "accompanying_period_comment",
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
initialComment() {
|
||||
return this.$store.state.accompanyingCourse.initialComment;
|
||||
},
|
||||
content: {
|
||||
set(value) {
|
||||
this.formdata.content = value;
|
||||
},
|
||||
get() {
|
||||
return (this.initialComment)? this.initialComment.content : null;
|
||||
}
|
||||
},
|
||||
errors() {
|
||||
return this.$store.state.errorMsg;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submitform() {
|
||||
console.log('submit');
|
||||
this.$store.dispatch('postFirstComment', this.formdata);
|
||||
},
|
||||
removeComment() {
|
||||
console.log('remove');
|
||||
this.$store.dispatch('postFirstComment', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* TODO
|
||||
* - [x] delete button in ul record_actions, but not in form
|
||||
* - [ ] display updatedAt => initialComment fetch PATCH content changes MUST NOT change object id !!
|
||||
* - [ ] ckeditor integration
|
||||
*/
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.vue-component > div {
|
||||
//margin: 1em;
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h2><a name="section-70"></a>
|
||||
{{ $t('confirm.title') }}
|
||||
</h2>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
{{ $t('confirm.text_draft') }}
|
||||
<span class="badge badge-secondary">{{ $t('course.step.draft') }}</span>
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('confirm.text_active') }}
|
||||
<span class="badge badge-primary">{{ $t('course.step.active') }}</span>
|
||||
</p>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-save" @click="modal.showModal = true">
|
||||
{{ $t('confirm.ok') }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal.showModal" :modalDialogClass="modal.modalDialogClass" @close="modal.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h2 class="modal-title">{{ $t('confirm.sure') }}</h2>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>{{ $t('confirm.sure_description') }}</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button red" @click="confirmCourse">
|
||||
{{ $t('confirm.ok') }}
|
||||
</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
|
||||
export default {
|
||||
name: "Confirm",
|
||||
components: {
|
||||
Modal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-centered modal-md"
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confirmCourse() {
|
||||
console.log('@@ CLICK confirmCourse');
|
||||
this.$store.dispatch('confirmAccompanyingCourse');
|
||||
console.log('confirm last');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.vue-component > div {
|
||||
//margin: 1em;
|
||||
}
|
||||
</style>
|
@@ -29,10 +29,12 @@
|
||||
</button>
|
||||
</li-->
|
||||
<li>
|
||||
<button class="sc-button bt-remove"
|
||||
<button v-if="!participation.endDate"
|
||||
class="sc-button bt-remove"
|
||||
:title="$t('action.remove')"
|
||||
@click.prevent="$emit('close', participation)">
|
||||
</button>
|
||||
<button v-else class="sc-button bt-remove disabled"></button>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
|
@@ -1,8 +1,12 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('persons_associated.title')}}</h3>
|
||||
<label>{{ $tc('persons_associated.counter', counter) }}</label>
|
||||
<table class="rounded">
|
||||
<h2><a name="section-10"></a>{{ $t('persons_associated.title')}}</h2>
|
||||
|
||||
<div>
|
||||
<label>{{ $tc('persons_associated.counter', counter) }}</label>
|
||||
</div>
|
||||
|
||||
<table class="rounded" v-if="participations.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-orange">{{ $t('persons_associated.firstname') }}</th>
|
||||
@@ -12,24 +16,28 @@
|
||||
<th class="chill-orange">{{ $t('action.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<person-item
|
||||
v-for="participation in participations"
|
||||
v-bind:participation="participation"
|
||||
v-bind:key="participation.id"
|
||||
<tbody>
|
||||
<person-item
|
||||
v-for="participation in participations"
|
||||
v-bind:participation="participation"
|
||||
v-bind:key="participation.id"
|
||||
@remove="removeParticipation"
|
||||
@close="closeParticipation">
|
||||
</person-item>
|
||||
</tbody>
|
||||
</table>
|
||||
<add-persons></add-persons>
|
||||
<ul class="record_actions">
|
||||
<!--li>
|
||||
<button class="sc-button orange" @click="savePersons">
|
||||
{{ $t('action.save') }}
|
||||
</button>
|
||||
</li-->
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<add-persons
|
||||
buttonTitle="persons_associated.add_persons"
|
||||
modalTitle="add_persons.title"
|
||||
v-bind:key="addPersons.key"
|
||||
v-bind:options="addPersons.options"
|
||||
@addNewPersons="addNewPersons"
|
||||
ref="addPersons"> <!-- to cast child method -->
|
||||
</add-persons>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -40,27 +48,44 @@ import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue'
|
||||
|
||||
export default {
|
||||
name: 'PersonsAssociated',
|
||||
components: {
|
||||
components: {
|
||||
PersonItem,
|
||||
AddPersons
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addPersons: {
|
||||
key: 'persons_associated',
|
||||
options: {
|
||||
type: ['person'],
|
||||
priority: null,
|
||||
uniq: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
participations: state => state.accompanyingCourse.participations,
|
||||
counter: state => state.accompanyingCourse.participations.length
|
||||
}),
|
||||
methods: {
|
||||
removeParticipation(item) {
|
||||
this.$store.dispatch('removeParticipation', item)
|
||||
console.log('@@ CLICK remove participation: item', item);
|
||||
this.$store.dispatch('removeParticipation', item);
|
||||
},
|
||||
closeParticipation(item) {
|
||||
console.log('@@ CLICK close participation: item', item);
|
||||
this.$store.dispatch('closeParticipation', item)
|
||||
this.$store.dispatch('closeParticipation', item);
|
||||
},
|
||||
/*
|
||||
savePersons() {
|
||||
console.log('[wip] saving persons');
|
||||
addNewPersons({ selected, modal }) {
|
||||
console.log('@@@ CLICK button addNewPersons', selected);
|
||||
selected.forEach(function(item) {
|
||||
this.$store.dispatch('addParticipation', item);
|
||||
}, this
|
||||
);
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h2><a name="section-40"></a>{{ $t('referrer.title') }}</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Referrer",
|
||||
}
|
||||
</script>
|
@@ -1,85 +1,118 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('requestor.title') }}</h3>
|
||||
{{ accompanyingCourse.id }}
|
||||
{{ accompanyingCourse.remark }}<br><br>
|
||||
|
||||
<!-- TESTS AREA -->
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal1.showModal = true">
|
||||
{{ $t('action.show_modal') }}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal2.showModal = true">
|
||||
Ouvrir une seconde modale
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<h2><a name="section-20"></a>{{ $t('requestor.title') }}</h2>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal1.showModal" :modalDialogClass="modal1.modalDialogClass" @close="modal1.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">Le titre de ma modale</h3>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal1.showModal = false; modal2.showModal = true">
|
||||
{{ $t('action.next')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal2.showModal" :modalDialogClass="modal2.modalDialogClass" @close="modal2.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">Une autre modale</h3>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>modal 2</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal2.showModal = false">
|
||||
{{ $t('action.save')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
<!-- END TESTS -->
|
||||
<div v-if="accompanyingCourse.requestor">
|
||||
<label>
|
||||
<input type="checkbox" v-model="isAnonymous" :value="value" />
|
||||
{{ $t('requestor.is_anonymous') }}
|
||||
</label>
|
||||
|
||||
<dt>{{ $t('requestor.type') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.type }}</dd>
|
||||
<dt>{{ $t('requestor.text') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.text }}</dd>
|
||||
<dt>{{ $t('requestor.is_anonymous') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestorAnonymous }}</dd>
|
||||
|
||||
<div v-if="accompanyingCourse.requestor.type === 'person'">
|
||||
<dt>{{ $t('requestor.person_id') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.person_id }}</dd>
|
||||
<dt>{{ $t('requestor.birthdate') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.requestor.birthdate.datetime, 'short') }}</dd>
|
||||
<dt>{{ $t('requestor.center') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.center.name }}</dd>
|
||||
<dt>{{ $t('requestor.firstName') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.firstName }}</dd>
|
||||
<dt>{{ $t('requestor.lastName') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.lastName }}</dd>
|
||||
<dt>{{ $t('requestor.phonenumber') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.phonenumber }}</dd>
|
||||
<dt>{{ $t('requestor.mobilenumber') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.mobilenumber }}</dd>
|
||||
<dt>{{ $t('requestor.altNames') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.altNames }}</dd>
|
||||
</div>
|
||||
|
||||
<div v-if="accompanyingCourse.requestor.type === 'thirdparty'">
|
||||
<dt>{{ $t('requestor.person_id') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.thirdparty_id }}</dd>
|
||||
<dt>{{ $t('requestor.address') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.address.text }}</dd>
|
||||
<dt>{{ $t('requestor.location') }}</dt>
|
||||
<dd>{{ accompanyingCourse.requestor.address.postcode.name }}</dd>
|
||||
</div>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-remove"
|
||||
:title="$t('action.remove')"
|
||||
@click="removeRequestor">
|
||||
{{ $t('action.remove') }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<add-persons v-if="accompanyingCourse.requestor === null"
|
||||
buttonTitle="requestor.add_requestor"
|
||||
modalTitle="requestor.add_requestor"
|
||||
v-bind:key="addPersons.key"
|
||||
v-bind:options="addPersons.options"
|
||||
@addNewPersons="addNewPersons"
|
||||
ref="addPersons"> <!-- to cast child method -->
|
||||
</add-persons>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal'
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue'
|
||||
|
||||
export default {
|
||||
name: 'Requestor',
|
||||
components: {
|
||||
Modal,
|
||||
AddPersons,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal1: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-xl" // modal-lg modal-md modal-sm
|
||||
},
|
||||
modal2: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-centered modal-sm" // modal-lg modal-md modal-sm
|
||||
addPersons: {
|
||||
key: 'requestor',
|
||||
options: {
|
||||
type: ['person', 'thirdparty'],
|
||||
priority: null,
|
||||
uniq: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
},
|
||||
isAnonymous: {
|
||||
set(value) {
|
||||
console.log('requestorIsAnonymous value',value);
|
||||
this.$store.dispatch('requestorIsAnonymous', value);
|
||||
},
|
||||
get() {
|
||||
return this.$store.state.accompanyingCourse.requestorAnonymous;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeRequestor() {
|
||||
console.log('@@ CLICK remove requestor: item');
|
||||
this.$store.dispatch('removeRequestor');
|
||||
},
|
||||
addNewPersons({ selected, modal }) {
|
||||
console.log('@@@ CLICK button addNewPersons', selected);
|
||||
this.$store.dispatch('addRequestor', selected.shift());
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-pill badge-secondary"
|
||||
v-bind:title="resource.resource.id">
|
||||
<span v-if="resource.resource.type === 'person'" >{{ $t('item.type_person') }}</span>
|
||||
<span v-if="resource.resource.type === 'thirdparty'" >{{ $t('item.type_thirdparty') }}</span>
|
||||
</span>
|
||||
{{ resource.resource.text }}
|
||||
</td>
|
||||
|
||||
<td v-if="resource.resource.type === 'person'">
|
||||
{{ $tc('person.born') }}{{ $d(resource.resource.birthdate.datetime, 'short') }}
|
||||
</td>
|
||||
<td v-else-if="resource.resource.type === 'thirdparty'">
|
||||
{{ resource.resource.address.text }}<br>
|
||||
{{ resource.resource.address.postcode.name }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="sc-button bt-show" target="_blank"
|
||||
:href="url.show"
|
||||
:title="$t('action.show')">
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="sc-button bt-update" target="_blank"
|
||||
:href="url.edit"
|
||||
:title="$t('action.edit')">
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
class="sc-button bt-remove"
|
||||
:title="$t('action.remove')"
|
||||
@click.prevent="$emit('remove', resource)">
|
||||
</button>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ResourceItem',
|
||||
props: ['resource'],
|
||||
emits: ['remove'],
|
||||
computed: {
|
||||
type() {
|
||||
return this.resource.resource.type;
|
||||
},
|
||||
url() {
|
||||
return (this.type === 'person') ? {
|
||||
show: `/fr/person/${this.resource.resource.id}/general`,
|
||||
edit: `/fr/person/${this.resource.resource.id}/general/edit`
|
||||
} : {
|
||||
show: `/fr/thirdparty/thirdparty/${this.resource.resource.id}/show`,
|
||||
edit: `/fr/thirdparty/thirdparty/${this.resource.resource.id}/update`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
|
||||
<h2><a name="section-50"></a>{{ $t('resources.title')}}</h2>
|
||||
|
||||
<div>
|
||||
<label>{{ $tc('resources.counter', counter) }}</label>
|
||||
</div>
|
||||
|
||||
<table class="rounded" v-if="resources.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-orange">{{ $t('resources.text') }}</th>
|
||||
<th class="chill-orange">{{ $t('resources.description') }}</th>
|
||||
<th class="chill-orange">{{ $t('action.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<resource-item
|
||||
v-for="resource in resources"
|
||||
v-bind:resource="resource"
|
||||
v-bind:key="resource.id"
|
||||
@remove="removeResource">
|
||||
</resource-item>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<add-persons
|
||||
buttonTitle="resources.add_resources"
|
||||
modalTitle="resources.add_resources"
|
||||
v-bind:key="addPersons.key"
|
||||
v-bind:options="addPersons.options"
|
||||
@addNewPersons="addNewPersons"
|
||||
ref="addPersons"> <!-- to cast child method -->
|
||||
</add-persons>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
|
||||
import ResourceItem from './ResourceItem.vue';
|
||||
|
||||
export default {
|
||||
name: 'Resources',
|
||||
components: {
|
||||
AddPersons,
|
||||
ResourceItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addPersons: {
|
||||
key: 'resources',
|
||||
options: {
|
||||
type: ['person', 'thirdparty'],
|
||||
priority: null,
|
||||
uniq: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
resources: state => state.accompanyingCourse.resources,
|
||||
counter: state => state.accompanyingCourse.resources.length
|
||||
}),
|
||||
methods: {
|
||||
removeResource(item) {
|
||||
console.log('@@ CLICK remove resource: item', item);
|
||||
this.$store.dispatch('removeResource', item);
|
||||
},
|
||||
addNewPersons({ selected, modal }) {
|
||||
console.log('@@@ CLICK button addNewPersons', selected);
|
||||
selected.forEach(function(item) {
|
||||
this.$store.dispatch('addResource', item);
|
||||
}, this
|
||||
);
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h2><a name="section-30"></a>{{ $t('social_issue.title') }}</h2>
|
||||
|
||||
<div class="my-4">
|
||||
<!--label for="selectIssues">{{ $t('social_issue.label') }}</label-->
|
||||
<VueMultiselect
|
||||
name="selectIssues"
|
||||
v-model="selected"
|
||||
track-by="id"
|
||||
label="text"
|
||||
:placeholder="$t('social_issue.label')"
|
||||
:multiple="true"
|
||||
:searchable="true"
|
||||
:close-on-select="false"
|
||||
:allow-empty="true"
|
||||
:show-labels="false"
|
||||
:options="options">
|
||||
</VueMultiselect>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueMultiselect from 'vue-multiselect'
|
||||
import { getSocialIssues } from '../api'
|
||||
|
||||
export default {
|
||||
name: "SocialIssue",
|
||||
components: { VueMultiselect },
|
||||
data () {
|
||||
return {
|
||||
selected: null,
|
||||
options: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
mounted() {
|
||||
this.getOptions();
|
||||
},
|
||||
methods: {
|
||||
getOptions() {
|
||||
getSocialIssues().then(socialIssues => new Promise((resolve, reject) => {
|
||||
console.log('socialIssues', socialIssues);
|
||||
this.options = socialIssues.results;
|
||||
resolve();
|
||||
})).catch(error => this.$store.commit('catchError', error));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
||||
<style lang="scss" scoped>
|
||||
div.vue-component > div {
|
||||
//margin: 3em;
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h2></a>Tests</h2>
|
||||
|
||||
<!-- Modal -->
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal1.showModal = true">
|
||||
{{ $t('action.show_modal') }}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal2.showModal = true">
|
||||
Ouvrir une seconde modale
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal1.showModal" :modalDialogClass="modal1.modalDialogClass" @close="modal1.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h2 class="modal-title">Le titre de ma modale</h2>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
|
||||
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal1.showModal = false; modal2.showModal = true">
|
||||
{{ $t('action.next')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal2.showModal" :modalDialogClass="modal2.modalDialogClass" @close="modal2.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h2 class="modal-title">Une autre modale</h2>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>modal 2</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal2.showModal = false">
|
||||
{{ $t('action.save')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
<!-- END Modal -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal'
|
||||
|
||||
export default {
|
||||
name: 'Test',
|
||||
components: {
|
||||
Modal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal1: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-xl" // modal-lg modal-md modal-sm
|
||||
},
|
||||
modal2: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-centered modal-sm" // modal-lg modal-md modal-sm
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div>
|
||||
<a @click="toggleIntensity" class="flag-toggle">
|
||||
{{ $t('course.occasional') }}
|
||||
<i class="fa" :class="{ 'fa-toggle-on': isRegular, 'fa-toggle-on fa-flip-horizontal': !isRegular }"></i>
|
||||
{{ $t('course.regular') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="badge badge-pill" :class="{ 'badge-primary': isEmergency, 'badge-secondary': !isEmergency }" @click="toggleEmergency">
|
||||
{{ $t('course.emergency') }}
|
||||
</button>
|
||||
<button class="badge badge-pill" :class="{ 'badge-primary': isConfidential, 'badge-secondary': !isConfidential }" @click="toggleConfidential">
|
||||
{{ $t('course.confidential') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
export default {
|
||||
name: "ToggleFlags",
|
||||
computed: {
|
||||
...mapState({
|
||||
intensity: state => state.accompanyingCourse.intensity,
|
||||
emergency: state => state.accompanyingCourse.emergency,
|
||||
confidential: state => state.accompanyingCourse.confidential,
|
||||
}),
|
||||
isRegular() {
|
||||
return (this.intensity === 'regular') ? true : false;
|
||||
},
|
||||
isEmergency() {
|
||||
return (this.emergency) ? true : false;
|
||||
},
|
||||
isConfidential() {
|
||||
return (this.confidential) ? true : false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIntensity() {
|
||||
let value;
|
||||
switch (this.intensity) {
|
||||
case "occasional":
|
||||
value = "regular";
|
||||
break;
|
||||
case "regular":
|
||||
value = "occasional";
|
||||
break;
|
||||
default:
|
||||
//temporaire (modif backend)
|
||||
value = "occasional";
|
||||
}
|
||||
this.$store.dispatch('toggleIntensity', value);
|
||||
},
|
||||
toggleEmergency() {
|
||||
this.$store.dispatch('toggleEmergency', (!this.isEmergency));
|
||||
},
|
||||
toggleConfidential() {
|
||||
this.$store.dispatch('toggleConfidential', (!this.isConfidential));
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a.flag-toggle {
|
||||
color: white;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
border-radius: 20px;
|
||||
}
|
||||
i {
|
||||
margin: auto 0.4em;
|
||||
}
|
||||
}
|
||||
button.badge {
|
||||
margin-left: 0.8em;
|
||||
&.badge-secondary {
|
||||
opacity: 0.5;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -4,24 +4,82 @@ const appMessages = {
|
||||
fr: {
|
||||
course: {
|
||||
id: "id",
|
||||
title: "Parcours",
|
||||
title: {
|
||||
draft: "Création d'un nouveau parcours",
|
||||
active: "Modification du parcours"
|
||||
},
|
||||
opening_date: "Date d'ouverture",
|
||||
closing_date: "Date de clôture",
|
||||
remark: "Commentaire",
|
||||
closing_motive: "Motif de clôture",
|
||||
user: "TMS",
|
||||
flags: "Indicateurs",
|
||||
status: "État",
|
||||
step: {
|
||||
draft: "Brouillon",
|
||||
active: "En file active"
|
||||
},
|
||||
open_at: "ouvert le ",
|
||||
by: "par ",
|
||||
emergency: "urgent",
|
||||
confidential: "confidentiel",
|
||||
regular: "régulier",
|
||||
occasional: "ponctuel"
|
||||
},
|
||||
persons_associated: {
|
||||
title: "Usagers concernés",
|
||||
counter: "Pas d'usager | 1 usager | {count} usagers",
|
||||
firstname: "Prénom",
|
||||
lastname: "Nom",
|
||||
startdate: "Date d'entrée",
|
||||
counter: "Il n'y a pas encore d'usager | 1 usager | {count} usagers",
|
||||
firstname: "Prénom",
|
||||
lastname: "Nom",
|
||||
startdate: "Date d'entrée",
|
||||
enddate: "Date de sortie",
|
||||
addPerson: "Ajouter un usager",
|
||||
add_persons: "Ajouter des usagers",
|
||||
},
|
||||
requestor: {
|
||||
title: "Demandeur",
|
||||
add_requestor: "Ajouter un demandeur",
|
||||
is_anonymous: "Le demandeur est anonyme",
|
||||
type: "Type",
|
||||
person_id: "id",
|
||||
text: "Dénomination",
|
||||
firstName: "Prénom",
|
||||
lastName: "Nom",
|
||||
birthdate: "Date de naissance",
|
||||
center: "Centre",
|
||||
phonenumber: "Téléphone",
|
||||
mobilenumber: "Mobile",
|
||||
altNames: "Autres noms",
|
||||
address: "Adresse",
|
||||
location: "Localité",
|
||||
},
|
||||
social_issue: {
|
||||
title: "Problématiques sociales",
|
||||
label: "Choisir les problématiques sociales",
|
||||
},
|
||||
referrer: {
|
||||
title: "Référent",
|
||||
},
|
||||
resources: {
|
||||
title: "Interlocuteurs privilégiés",
|
||||
counter: "Il n'y a pas encore d'interlocuteur | 1 interlocuteur | {count} interlocuteurs",
|
||||
text: "Dénomination",
|
||||
description: "Description",
|
||||
add_resources: "Ajouter des interlocuteurs",
|
||||
},
|
||||
comment: {
|
||||
title: "Observations",
|
||||
label: "Ajout d'une note",
|
||||
content: "Rédigez une première note..."
|
||||
},
|
||||
confirm: {
|
||||
title: "Confirmation",
|
||||
text_draft: "Le parcours est actuellement à l'état de ",
|
||||
text_active: "En validant cette étape, vous lui donnez le statut ",
|
||||
sure: "Êtes-vous sûr ?",
|
||||
sure_description: "Une fois le changement confirmé, il n'est plus possible de le remettre à l'état de brouillon !",
|
||||
ok: "Confirmer le parcours"
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,11 +1,14 @@
|
||||
import 'es6-promise/auto';
|
||||
import { createStore } from 'vuex';
|
||||
import addPersons from './modules/addPersons'
|
||||
import { getAccompanyingCourse, postParticipation } from '../api';
|
||||
import { getAccompanyingCourse,
|
||||
patchAccompanyingCourse,
|
||||
confirmAccompanyingCourse,
|
||||
postParticipation,
|
||||
postRequestor,
|
||||
postResource } from '../api';
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const id = window.accompanyingCourseId; //tmp
|
||||
const id = window.accompanyingCourseId;
|
||||
|
||||
let initPromise = getAccompanyingCourse(id)
|
||||
.then(accompanying_course => new Promise((resolve, reject) => {
|
||||
@@ -13,7 +16,6 @@ let initPromise = getAccompanyingCourse(id)
|
||||
const store = createStore({
|
||||
strict: debug,
|
||||
modules: {
|
||||
addPersons
|
||||
},
|
||||
state: {
|
||||
accompanyingCourse: accompanying_course,
|
||||
@@ -22,54 +24,168 @@ let initPromise = getAccompanyingCourse(id)
|
||||
getters: {
|
||||
},
|
||||
mutations: {
|
||||
removeParticipation(state, item) {
|
||||
//console.log('mutation: remove item', item.id);
|
||||
state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== item);
|
||||
catchError(state, error) {
|
||||
state.errorMsg.push(error);
|
||||
},
|
||||
removeParticipation(state, participation) {
|
||||
//console.log('### mutation: remove participation', participation.id);
|
||||
state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(element => element !== participation);
|
||||
},
|
||||
closeParticipation(state, { participation, payload }) {
|
||||
console.log('### mutation: close item', { participation, payload });
|
||||
// trouve dans le state le payload et le supprime du state
|
||||
state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== payload);
|
||||
// pousse la participation
|
||||
state.accompanyingCourse.participations.push(participation);
|
||||
//console.log('### mutation: close item', { participation, payload });
|
||||
// find row position and replace by closed participation
|
||||
state.accompanyingCourse.participations.splice(
|
||||
state.accompanyingCourse.participations.findIndex(element => element === payload), 1, participation
|
||||
);
|
||||
},
|
||||
addParticipation(state, participation) {
|
||||
//console.log('### mutation: add participation', participation);
|
||||
state.accompanyingCourse.participations.push(participation);
|
||||
},
|
||||
removeRequestor(state) {
|
||||
//console.log('### mutation: removeRequestor');
|
||||
state.accompanyingCourse.requestor = null;
|
||||
},
|
||||
addRequestor(state, requestor) {
|
||||
//console.log('### mutation: addRequestor', requestor);
|
||||
state.accompanyingCourse.requestor = requestor;
|
||||
},
|
||||
requestorIsAnonymous(state, value) {
|
||||
//console.log('### mutation: requestorIsAnonymous', value);
|
||||
state.accompanyingCourse.requestorAnonymous = value;
|
||||
},
|
||||
removeResource(state, resource) {
|
||||
//console.log('### mutation: removeResource', resource);
|
||||
state.accompanyingCourse.resources = state.accompanyingCourse.resources.filter(element => element !== resource);
|
||||
},
|
||||
addResource(state, resource) {
|
||||
//console.log('### mutation: addResource', resource);
|
||||
state.accompanyingCourse.resources.push(resource);
|
||||
},
|
||||
toggleIntensity(state, value) {
|
||||
state.accompanyingCourse.intensity = value;
|
||||
},
|
||||
toggleEmergency(state, value) {
|
||||
//console.log('### mutation: toggleEmergency');
|
||||
state.accompanyingCourse.emergency = value;
|
||||
},
|
||||
toggleConfidential(state, value) {
|
||||
//console.log('### mutation: toggleConfidential');
|
||||
state.accompanyingCourse.confidential = value;
|
||||
},
|
||||
postFirstComment(state, comment) {
|
||||
console.log('### mutation: postFirstComment', comment);
|
||||
state.accompanyingCourse.initialComment = comment;
|
||||
},
|
||||
confirmAccompanyingCourse(state, response) {
|
||||
//console.log('### mutation: confirmAccompanyingCourse: response', response);
|
||||
state.accompanyingCourse.step = response.step;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
removeParticipation({ commit }, payload) {
|
||||
commit('removeParticipation', payload);
|
||||
// fetch DELETE request...
|
||||
},
|
||||
closeParticipation({ commit }, payload) {
|
||||
//console.log('## action: fetch delete participation: payload', payload.person.id);
|
||||
postParticipation(id, payload.person.id, 'DELETE')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
//console.log('payload', payload);
|
||||
commit('closeParticipation', { participation, payload });
|
||||
resolve();
|
||||
}))
|
||||
.catch((error) => {
|
||||
state.errorMsg.push(error.message);
|
||||
});
|
||||
//console.log('## action: fetch delete participation: payload', payload);
|
||||
postParticipation(id, payload.person, 'DELETE')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
commit('closeParticipation', { participation, payload });
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
addParticipation(addPersons, payload) {
|
||||
//console.log('## action: fetch post participation: payload', payload.id);
|
||||
postParticipation(id, payload.id, 'POST')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
//console.log(participation, payload);
|
||||
addPersons.commit('addParticipation', participation);
|
||||
addPersons.commit('resetState', payload);
|
||||
resolve();
|
||||
}))
|
||||
.catch((error) => {
|
||||
state.errorMsg.push(error.message);
|
||||
});
|
||||
addParticipation({ commit }, payload) {
|
||||
//console.log('## action: fetch post participation (select item): payload', payload);
|
||||
postParticipation(id, payload.result, 'POST')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
commit('addParticipation', participation);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
removeRequestor({ commit, dispatch }) {
|
||||
//console.log('## action: fetch delete requestor');
|
||||
postRequestor(id, null, 'DELETE')
|
||||
.then(requestor => new Promise((resolve, reject) => {
|
||||
commit('removeRequestor');
|
||||
dispatch('requestorIsAnonymous', false);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
addRequestor({ commit }, payload) {
|
||||
//console.log('## action: fetch post requestor: payload', payload);
|
||||
postRequestor(id, payload.result, 'POST')
|
||||
.then(requestor => new Promise((resolve, reject) => {
|
||||
commit('addRequestor', requestor);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
requestorIsAnonymous({ commit }, payload) {
|
||||
//console.log('## action: fetch patch AccompanyingCourse: payload', payload);
|
||||
patchAccompanyingCourse(id, { type: "accompanying_period", requestorAnonymous: payload })
|
||||
.then(course => new Promise((resolve, reject) => {
|
||||
commit('requestorIsAnonymous', course.requestorAnonymous)
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
removeResource({ commit }, payload) {
|
||||
//console.log('## action: fetch postResource: payload', payload);
|
||||
postResource(id, payload, 'DELETE')
|
||||
.then(resource => new Promise((resolve, reject) => {
|
||||
commit('removeResource', payload) // mieux un retour de l'objet !
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
addResource({ commit }, payload) {
|
||||
//console.log('## action: fetch postResource: payload', payload);
|
||||
postResource(id, payload.result, 'POST')
|
||||
.then(resource => new Promise((resolve, reject) => {
|
||||
commit('addResource', resource)
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
toggleIntensity({ commit }, payload) {
|
||||
console.log(payload);
|
||||
patchAccompanyingCourse(id, { type: "accompanying_period", intensity: payload })
|
||||
.then(course => new Promise((resolve, reject) => {
|
||||
commit('toggleIntensity', course.intensity);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
toggleEmergency({ commit }, payload) {
|
||||
patchAccompanyingCourse(id, { type: "accompanying_period", emergency: payload })
|
||||
.then(course => new Promise((resolve, reject) => {
|
||||
commit('toggleEmergency', course.emergency);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
toggleConfidential({ commit }, payload) {
|
||||
patchAccompanyingCourse(id, { type: "accompanying_period", confidential: payload })
|
||||
.then(course => new Promise((resolve, reject) => {
|
||||
commit('toggleConfidential', course.confidential);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
postFirstComment({ commit }, payload) {
|
||||
console.log('## action: postFirstComment: payload', payload);
|
||||
patchAccompanyingCourse(id, { type: "accompanying_period", initialComment: payload })
|
||||
.then(course => new Promise((resolve, reject) => {
|
||||
commit('postFirstComment', course.initialComment);
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
},
|
||||
|
||||
confirmAccompanyingCourse({ commit }) {
|
||||
console.log('## action: confirmAccompanyingCourse');
|
||||
confirmAccompanyingCourse(id)
|
||||
.then(response => new Promise((resolve, reject) => {
|
||||
commit('confirmAccompanyingCourse', response);
|
||||
console.log('fetch resolve'); // redirection with #top anchor
|
||||
resolve();
|
||||
})).catch((error) => { commit('catchError', error) });
|
||||
}
|
||||
}
|
||||
});
|
||||
//console.log('store object', store.state.accompanyingCourse.id);
|
||||
resolve(store);
|
||||
}));
|
||||
|
||||
|
@@ -1,76 +0,0 @@
|
||||
import { searchPersons } from 'ChillPersonAssets/vuejs/_api/AddPersons'
|
||||
import { postParticipation } from '../../api';
|
||||
|
||||
|
||||
// initial state
|
||||
const state = {
|
||||
query: "",
|
||||
suggested: [],
|
||||
selected: []
|
||||
}
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
selectedAndSuggested: state => {
|
||||
const uniqBy = (a, key) => [
|
||||
...new Map(
|
||||
a.map(x => [key(x), x])
|
||||
).values()
|
||||
];
|
||||
let union = [...new Set([
|
||||
...state.suggested.slice().reverse(),
|
||||
...state.selected.slice().reverse(),
|
||||
])];
|
||||
return uniqBy(union, k => k.id);
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
setQuery(state, query) {
|
||||
//console.log('q=', query);
|
||||
state.query = query;
|
||||
},
|
||||
loadSuggestions(state, suggested) {
|
||||
state.suggested = suggested;
|
||||
},
|
||||
updateSelected(state, value) {
|
||||
state.selected = value;
|
||||
},
|
||||
resetState(state, selected) {
|
||||
//console.log('avant', state.selected);
|
||||
state.selected = state.selected.filter(value => value !== selected);
|
||||
//console.log('après', state.selected);
|
||||
state.query = "";
|
||||
state.suggested = [];
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
setQuery({ commit }, payload) {
|
||||
//console.log('## action: setquery: payload', payload);
|
||||
commit('setQuery', payload.query);
|
||||
if (payload.query.length >= 3) {
|
||||
searchPersons(payload.query)
|
||||
.then(suggested => new Promise((resolve, reject) => {
|
||||
commit('loadSuggestions', suggested.results);
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
commit('loadSuggestions', []);
|
||||
}
|
||||
},
|
||||
updateSelected({ commit }, payload) {
|
||||
//console.log('## action: update selected values: payload', payload);
|
||||
commit('updateSelected', payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
//namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
@@ -1,15 +1,23 @@
|
||||
const
|
||||
locale = 'fr',
|
||||
format = 'json'
|
||||
;
|
||||
/*
|
||||
* Build query string with query and options
|
||||
*/
|
||||
const parametersToString = ({ query, options }) => {
|
||||
let types ='';
|
||||
options.type.forEach(function(type) {
|
||||
types += '&type[]=' + type;
|
||||
});
|
||||
return 'q=' + query + types;
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_search, method GET, get a list of persons
|
||||
* Endpoint chill_person_search
|
||||
* method GET, get a list of persons
|
||||
*
|
||||
* @query string - the query to search for
|
||||
*/
|
||||
let searchPersons = (query) => {
|
||||
let url = `/${locale}/search.${format}?name=person_regular&q=${query}`;
|
||||
const searchPersons = ({ query, options }) => {
|
||||
let queryStr = parametersToString({ query, options });
|
||||
let url = `/fr/search.json?name=person_regular&${queryStr}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
@@ -17,4 +25,22 @@ let searchPersons = (query) => {
|
||||
});
|
||||
};
|
||||
|
||||
export { searchPersons };
|
||||
/*
|
||||
* Endpoint v.2 chill_main_search_global
|
||||
* method GET, get a list of persons and thirdparty
|
||||
*
|
||||
* NOTE: this is a temporary WIP endpoint, return inconsistent random results
|
||||
* @query string - the query to search for
|
||||
*/
|
||||
const searchPersons_2 = ({ query, options }) => {
|
||||
let queryStr = parametersToString({ query, options });
|
||||
let url = `/api/1.0/search.json?${queryStr}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export { searchPersons, searchPersons_2 };
|
||||
|
@@ -1,73 +1,91 @@
|
||||
<template>
|
||||
<button class="sc-button bt-create centered mt-4" @click="openModal">
|
||||
{{ $t('add_persons.search_add_others_persons') }}
|
||||
</button>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="openModal">
|
||||
{{ $t(buttonTitle) }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal.showModal"
|
||||
:modalDialogClass="modal.modalDialogClass"
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<modal v-if="modal.showModal"
|
||||
:modalDialogClass="modal.modalDialogClass"
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">{{ $t('add_persons.title') }}</h3>
|
||||
<h3 class="modal-title">{{ $t(modalTitle) }}</h3>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-fixed>
|
||||
<div class="search">
|
||||
<label style="float: right;">
|
||||
{{ $tc('add_persons.suggested_counter', suggestedCounter) }}
|
||||
</label>
|
||||
|
||||
<input id="search-persons"
|
||||
name="query"
|
||||
v-model="query"
|
||||
:placeholder="$t('add_persons.search_some_persons')"
|
||||
ref="search" />
|
||||
<i class="fa fa-search fa-lg"></i>
|
||||
<template v-slot:body-head>
|
||||
<div class="modal-body">
|
||||
<div class="search">
|
||||
|
||||
<label style="float: right;">
|
||||
{{ $tc('add_persons.suggested_counter', suggestedCounter) }}
|
||||
</label>
|
||||
|
||||
<input id="search-persons"
|
||||
name="query"
|
||||
v-model="query"
|
||||
:placeholder="$t('add_persons.search_some_persons')"
|
||||
ref="search" />
|
||||
<i class="fa fa-search fa-lg"></i>
|
||||
<i class="fa fa-times" v-if="queryLength >= 3" @click="resetSuggestion"></i>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:body>
|
||||
<!--span class="discret">Selection: {{ selected }}</span-->
|
||||
<div class="results">
|
||||
<div class="modal-body" v-if="checkUniq === 'checkbox'">
|
||||
<div class="count">
|
||||
<span>
|
||||
<a v-if="suggestedCounter > 0" href="#">
|
||||
{{ $t('action.check_all')}}</a>
|
||||
<a v-if="selectedCounter > 0" href="#">
|
||||
{{ $t('action.reset')}}</a>
|
||||
<a v-if="suggestedCounter > 2" @click="selectAll">
|
||||
{{ $t('action.check_all')}}
|
||||
</a>
|
||||
<a v-if="selectedCounter > 0" @click="resetSelection">
|
||||
<i v-if="suggestedCounter > 2"> • </i>
|
||||
{{ $t('action.reset')}}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="selectedCounter > 0">
|
||||
{{ $tc('add_persons.selected_counter', selectedCounter) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<person-suggestion
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:body>
|
||||
<!--span class="discret">Selection: {{ selected }}</span-->
|
||||
<div class="results">
|
||||
|
||||
<person-suggestion
|
||||
v-for="item in this.selectedAndSuggested.slice().reverse()"
|
||||
v-bind:item="item"
|
||||
v-bind:key="item.id">
|
||||
v-bind:key="itemKey(item)"
|
||||
v-bind:item="item"
|
||||
v-bind:search="search"
|
||||
v-bind:type="checkUniq"
|
||||
@updateSelected="updateSelected">
|
||||
</person-suggestion>
|
||||
|
||||
|
||||
<button v-if="query.length >= 3" class="sc-button bt-create ml-5 mt-2" name="createPerson">
|
||||
{{ $t('action.create') }} "{{ query }}"
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="addNewPersons">
|
||||
<button class="sc-button green"
|
||||
@click.prevent="$emit('addNewPersons', { selected, modal })">
|
||||
<i class="fa fa-plus fa-fw"></i>{{ $t('action.add')}}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
|
||||
</modal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
import PersonSuggestion from 'ChillPersonAssets/vuejs/_components/PersonSuggestion';
|
||||
import PersonSuggestion from './AddPersons/PersonSuggestion';
|
||||
import { searchPersons, searchPersons_2 } from 'ChillPersonAssets/vuejs/_api/AddPersons';
|
||||
|
||||
export default {
|
||||
name: 'AddPersons',
|
||||
@@ -75,40 +93,69 @@ export default {
|
||||
Modal,
|
||||
PersonSuggestion,
|
||||
},
|
||||
props: [
|
||||
'buttonTitle',
|
||||
'modalTitle',
|
||||
'options'
|
||||
],
|
||||
emits: ['addNewPersons'],
|
||||
data() {
|
||||
return {
|
||||
modal: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-xl"
|
||||
},
|
||||
search: {
|
||||
query: "",
|
||||
suggested: [],
|
||||
selected: []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
addPersons: state => state.addPersons
|
||||
}),
|
||||
query: {
|
||||
set(query) {
|
||||
this.$store.dispatch('setQuery', { query });
|
||||
return this.setQuery(query);
|
||||
},
|
||||
get() {
|
||||
return this.addPersons.query;
|
||||
return this.search.query;
|
||||
}
|
||||
},
|
||||
queryLength() {
|
||||
return this.search.query.length;
|
||||
},
|
||||
suggested() {
|
||||
return this.addPersons.suggested;
|
||||
return this.search.suggested;
|
||||
},
|
||||
suggestedCounter() {
|
||||
return this.addPersons.suggested.length;
|
||||
},
|
||||
return this.search.suggested.length;
|
||||
},
|
||||
selected() {
|
||||
return this.addPersons.selected;
|
||||
},
|
||||
return this.search.selected;
|
||||
},
|
||||
selectedCounter() {
|
||||
return this.addPersons.selected.length;
|
||||
return this.search.selected.length;
|
||||
},
|
||||
selectedAndSuggested() {
|
||||
return this.$store.getters.selectedAndSuggested;
|
||||
const uniqBy = (a, key) => [
|
||||
...new Map(
|
||||
a.map(x => [key(x), x])
|
||||
).values()
|
||||
];
|
||||
let union = [...new Set([
|
||||
...this.suggested.slice().reverse(),
|
||||
...this.selected.slice().reverse(),
|
||||
])];
|
||||
return uniqBy(union, k => k.key);
|
||||
},
|
||||
options() {
|
||||
return this.options;
|
||||
},
|
||||
checkUniq() {
|
||||
if (this.options.uniq === true) {
|
||||
return 'radio';
|
||||
}
|
||||
return 'checkbox';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -118,15 +165,90 @@ export default {
|
||||
this.$refs.search.focus();
|
||||
})
|
||||
},
|
||||
addNewPersons() {
|
||||
console.log('@@@ CLICK button addPersons')
|
||||
this.selected.forEach(function(item) {
|
||||
//console.log('# dispatch action for each item', item);
|
||||
this.$store.dispatch('addParticipation', item);
|
||||
}, this
|
||||
);
|
||||
this.modal.showModal = false;
|
||||
setQuery(query) {
|
||||
this.search.query = query;
|
||||
if (query.length >= 3) {
|
||||
searchPersons_2({ query, options: this.options })
|
||||
.then(suggested => new Promise((resolve, reject) => {
|
||||
console.log('suggested', suggested);
|
||||
this.loadSuggestions(suggested.results);
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
this.loadSuggestions([]);
|
||||
}
|
||||
},
|
||||
loadSuggestions(suggested) {
|
||||
console.log('suggested', suggested);
|
||||
this.search.suggested = suggested;
|
||||
this.search.suggested.forEach(function(item) {
|
||||
item.key = this.itemKey(item);
|
||||
}, this);
|
||||
},
|
||||
updateSelected(value) {
|
||||
console.log('value', value);
|
||||
this.search.selected = value;
|
||||
},
|
||||
resetSearch() {
|
||||
this.resetSelection();
|
||||
this.resetSuggestion();
|
||||
},
|
||||
resetSuggestion() {
|
||||
this.search.query = "";
|
||||
this.search.suggested = [];
|
||||
},
|
||||
resetSelection() {
|
||||
this.search.selected = [];
|
||||
},
|
||||
selectAll() {
|
||||
this.search.suggested.forEach(function(item) {
|
||||
this.search.selected.push(item);
|
||||
}, this);
|
||||
},
|
||||
itemKey(item) {
|
||||
return item.result.type + item.result.id;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
div.body-head {
|
||||
overflow-y: unset;
|
||||
div.modal-body:first-child {
|
||||
margin: auto 4em;
|
||||
div.search {
|
||||
position: relative;
|
||||
input {
|
||||
padding: 1.2em 1.5em 1.2em 2.5em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
i {
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
padding: 0.65em 0;
|
||||
top: 50%;
|
||||
}
|
||||
i.fa-search {
|
||||
left: 0.5em;
|
||||
}
|
||||
i.fa-times {
|
||||
right: 1em;
|
||||
padding: 0.75em 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.modal-body:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
div.count {
|
||||
margin: -0.5em 0 0.7em;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div class="list-item" :class="{ checked: isChecked }">
|
||||
|
||||
<div class="container">
|
||||
<input
|
||||
v-bind:type="type"
|
||||
v-model="selected"
|
||||
name="item"
|
||||
v-bind:id="item"
|
||||
v-bind:value="setValueByType(item, type)" />
|
||||
</div>
|
||||
|
||||
<suggestion-person
|
||||
v-if="item.result.type === 'person'"
|
||||
v-bind:item="item">
|
||||
</suggestion-person>
|
||||
|
||||
<suggestion-third-party
|
||||
v-if="item.result.type === 'thirdparty'"
|
||||
v-bind:item="item">
|
||||
</suggestion-third-party>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SuggestionPerson from './TypePerson';
|
||||
import SuggestionThirdParty from './TypeThirdParty';
|
||||
|
||||
export default {
|
||||
name: 'PersonSuggestion',
|
||||
components: {
|
||||
SuggestionPerson,
|
||||
SuggestionThirdParty,
|
||||
},
|
||||
props: [
|
||||
'item',
|
||||
'search',
|
||||
'type'
|
||||
],
|
||||
emits: ['updateSelected'],
|
||||
computed: {
|
||||
selected: {
|
||||
set(value) {
|
||||
console.log('value', value);
|
||||
this.$emit('updateSelected', value);
|
||||
},
|
||||
get() {
|
||||
return this.search.selected;
|
||||
}
|
||||
},
|
||||
isChecked() {
|
||||
return (this.search.selected.indexOf(this.item) === -1) ? false : true;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setValueByType(value, type) {
|
||||
return (type === 'radio')? [value] : value;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
div.results {
|
||||
div.list-item {
|
||||
padding: 0.4em 0.8em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
&.checked {
|
||||
background-color: #ececec;
|
||||
border-bottom: 1px dotted #8b8b8b;
|
||||
}
|
||||
div.container {
|
||||
& > input {
|
||||
margin-right: 0.8em;
|
||||
}
|
||||
span:not(.name) {
|
||||
margin-left: 0.5em;
|
||||
opacity: 0.5;
|
||||
font-size: 90%;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
div.right_actions {
|
||||
margin: 0 0 0 auto;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
& > * {
|
||||
margin-left: 0.5em;
|
||||
align-self: baseline;
|
||||
}
|
||||
a.sc-button {
|
||||
border: 1px solid lightgrey;
|
||||
font-size: 70%;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
|
||||
<span class="name">
|
||||
{{ item.result.text }}
|
||||
</span>
|
||||
<span class="birthday">
|
||||
{{ $d(item.result.birthdate.datetime, 'short') }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
<span class="badge badge-pill badge-secondary" :title="item.key">
|
||||
{{ $t('item.type_person') }}
|
||||
</span>
|
||||
<a class="sc-button bt-show" target="_blank" :title="item.key" :href="url.show"></a>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SuggestionPerson',
|
||||
props: ['item'],
|
||||
data() {
|
||||
return {
|
||||
url: {
|
||||
show: '/fr/person/' + this.item.result.person_id + '/general',
|
||||
edit: '/fr/person/' + this.item.result.person_id + '/general/edit'
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
|
||||
<span class="name">
|
||||
{{ item.result.text }}
|
||||
</span>
|
||||
<span class="location">
|
||||
{{ item.result.address.text }} -
|
||||
{{ item.result.address.postcode.name }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
<span class="badge badge-pill badge-secondary" :title="item.key">
|
||||
{{ $t('item.type_thirdparty') }}
|
||||
</span>
|
||||
<a class="sc-button bt-show" target="_blank" :title="item.key" :href="url.show"></a>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SuggestionThirdParty',
|
||||
props: ['item'],
|
||||
data() {
|
||||
return {
|
||||
url: {
|
||||
show: '/fr/thirdparty/thirdparty/' + this.item.result.thirdparty_id + '/show',
|
||||
edit: '/fr/thirdparty/thirdparty/' + this.item.result.thirdparty_id + '/edit'
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
@@ -1,53 +0,0 @@
|
||||
<template>
|
||||
<div class="list-item" :class="{ checked: isChecked }">
|
||||
<div class="container">
|
||||
|
||||
<!--a class="discret" target="_blank" :href="url.show">{{ item.id }}</a-->
|
||||
<input class=""
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
:value="item" />
|
||||
|
||||
{{ item.text }}
|
||||
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
<span class="badge badge-pill badge-secondary" :title="item.id">
|
||||
{{ $t('item.type_person') }}
|
||||
</span>
|
||||
<a class="sc-button bt-show" target="_blank" :title="item.id" :href="url.show"></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'PersonSuggestion',
|
||||
props: ['item'],
|
||||
data() {
|
||||
return {
|
||||
url: {
|
||||
show: '/fr/person/' + this.item.id + '/general',
|
||||
edit: '/fr/person/' + this.item.id + '/general/edit'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selected: {
|
||||
set(value) {
|
||||
this.$store.dispatch('updateSelected', value);
|
||||
},
|
||||
get() {
|
||||
return this.$store.state.addPersons.selected;
|
||||
}
|
||||
},
|
||||
isChecked() {
|
||||
return (this.selected.indexOf(this.item) === -1) ? false : true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@@ -1,7 +1,6 @@
|
||||
const personMessages = {
|
||||
fr: {
|
||||
add_persons: {
|
||||
search_add_others_persons: "Rechercher et ajouter d'autres usagers",
|
||||
title: "Ajouter des usagers",
|
||||
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
|
||||
selected_counter: " 1 sélectionné | {count} sélectionnés",
|
||||
@@ -9,10 +8,16 @@ const personMessages = {
|
||||
},
|
||||
item: {
|
||||
type_person: "Usager",
|
||||
type_tms: "TMS",
|
||||
type_3rdparty: "Tiers",
|
||||
type_menage: "Ménage"
|
||||
}
|
||||
type_user: "TMS",
|
||||
type_thirdparty: "Tiers",
|
||||
type_household: "Ménage"
|
||||
},
|
||||
person: {
|
||||
firstname: "Prénom",
|
||||
lastname: "Nom",
|
||||
born: "né le ",
|
||||
},
|
||||
error_only_one_person: "Une seule personne peut être sélectionnée !"
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -2,39 +2,24 @@
|
||||
<div class="grid-12 parent" id="header-accompanying_course-name" >
|
||||
<div class="grid-10 push-1 grid-mobile-12 grid-tablet-12 push-mobile-0 push-tablet-0 parent">
|
||||
|
||||
<div class="grid-5">{% set title = title %}
|
||||
<div class="grid-6">{% set title = title %}
|
||||
<h1>
|
||||
<i class="fa fa-random fa-fw"></i>
|
||||
{{ 'Accompanying Course'|trans }}{# ou défini en amont
|
||||
{{ title|default('Accompanying Course'|trans)|raw }} #}
|
||||
<span style="font-weight: lighter; font-size: 65%;">(n°{{ accompanyingCourse.id }})</span>
|
||||
{{ 'Accompanying Course'|trans }}
|
||||
<span style="font-weight: lighter; font-size: 50%;">(n°{{ accompanyingCourse.id }})</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="grid-4">
|
||||
<ul class="record_actions">
|
||||
<li>ponctuel <i class="fa fa-toggle-on fa-fw"></i> régulier</li>
|
||||
<li>ouvert</li>
|
||||
<li>en file active</li>
|
||||
<li>urgent</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="grid-3" id="banner-flags"></div>
|
||||
|
||||
<div class="grid-3">
|
||||
<p style="text-align: right;">
|
||||
<i>ouvert le 11 avril 2019</i><br>
|
||||
par <b>Soline Maillet | SIPAS</b>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid-3" id="banner-status"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-12 parent" id="header-accompanying_course-details" >
|
||||
<div class="grid-10 push-1 grid-mobile-12 grid-tablet-12 push-mobile-0 push-tablet-0 parent">
|
||||
|
||||
<div class="grid-4">Problématiques sociales</div>
|
||||
<div class="grid-4">_</div>
|
||||
<div class="grid-4">_</div>
|
||||
<div id="banner-social-issues"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -6,21 +6,23 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ block('title') }}</h1>
|
||||
{% if 'DRAFT' == accompanyingCourse.step %}
|
||||
<div class="grid-8 centered error flash_message">
|
||||
<span>
|
||||
{{ 'This accompanying course is still a draft'|trans }}
|
||||
<a href="{{ path('chill_person_accompanying_course_show', { 'accompanying_period_id': accompanyingCourse.id } ) }}">
|
||||
{{ 'Edit & activate accompanying course'|trans }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<pre>
|
||||
{{ 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 }} | <a href="{{ path('chill_person_accompanying_period_list', { person_id: p.person.id }) }}">{{ p.person.fullnamecanonical }}</a> | {{ p.startdate|format_date('short') }} | {{ p.enddate|format_date('short') }}
|
||||
{% endfor %}
|
||||
</pre>
|
||||
<h1>{{ 'Associated peoples'|trans }}</h1>
|
||||
|
||||
{{ dump() }}
|
||||
<h1>{{ 'Resources'|trans }}</h1>
|
||||
|
||||
<h1>{{ 'Social actions'|trans }}</h1>
|
||||
|
||||
<h1>{{ 'Last events on accompanying course'|trans }}</h1>
|
||||
|
||||
{% endblock %}
|
||||
|
@@ -1,12 +1,17 @@
|
||||
{% extends 'ChillPersonBundle:AccompanyingCourse:layout.html.twig' %}
|
||||
|
||||
{% set title = 'DRAFT' == accompanyingCourse.step ? 'New accompanying course' : 'Edit accompanying course' %}
|
||||
|
||||
{% block title %}
|
||||
{{ 'Edit Accompanying Course'|trans }}
|
||||
{{ title|trans }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ block('title') }}</h1>
|
||||
<div id="accompanying-course"></div>
|
||||
<div id="accompanying-course"></div> {# <== insert accompanyingCourse vue component #}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('accompanying_course') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
|
@@ -49,4 +49,22 @@
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
|
||||
NEW FORM
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ block('title') }}</h1>
|
||||
<div id="address"></div>
|
||||
{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<link href="{{ asset('build/address.css') }}" type="text/css" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_script_tags('address') }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
@@ -38,6 +38,9 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRole
|
||||
}
|
||||
|
||||
// TODO take scopes into account
|
||||
if (count($subject->getPersons()) === 0) {
|
||||
return true;
|
||||
}
|
||||
foreach ($subject->getPersons() as $person) {
|
||||
// give access as soon as on center is reachable
|
||||
if ($this->helper->userHasAccess($token->getUser(), $person->getCenter(), $attribute)) {
|
||||
|
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2014-2021, 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\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
|
||||
|
||||
class AccompanyingPeriodNormalizer implements NormalizerInterface, NormalizerAwareInterface {
|
||||
|
||||
protected ?NormalizerInterface $normalizer = null;
|
||||
|
||||
public function normalize($period, string $format = null, array $context = array())
|
||||
{
|
||||
/** @var AccompanyingPeriod $period */
|
||||
return [
|
||||
'id' => $period->getId(),
|
||||
'openingDate' => $this->normalizer->normalize($period->getOpeningDate(), $format),
|
||||
'closingDate' => $this->normalizer->normalize($period->getClosingDate(), $format),
|
||||
'remark' => $period->getRemark(),
|
||||
'participations' => $this->normalizer->normalize($period->getParticipations(), $format),
|
||||
'closingMotive' => $this->normalizer->normalize($period->getClosingMotive(), $format),
|
||||
'user' => $this->normalizer->normalize($period->getUser(), $format),
|
||||
'step' => $period->getStep(),
|
||||
'origin' => $this->normalizer->normalize($period->getOrigin(), $format),
|
||||
'intensity' => $period->getIntensity(),
|
||||
'emergency' => $period->isEmergency(),
|
||||
'confidential' => $period->isConfidential()
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return $data instanceof AccompanyingPeriod;
|
||||
}
|
||||
|
||||
public function setNormalizer(NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
}
|
@@ -41,6 +41,7 @@ class AccompanyingPeriodParticipationNormalizer implements NormalizerInterface,
|
||||
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return false;
|
||||
return $data instanceof AccompanyingPeriodParticipation;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\ResourceRepository;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
|
||||
use Symfony\Component\Serializer\Exception;
|
||||
use Chill\MainBundle\Serializer\Normalizer\DiscriminatedObjectDenormalizer;
|
||||
|
||||
|
||||
class AccompanyingPeriodResourceNormalizer implements DenormalizerInterface, DenormalizerAwareInterface
|
||||
{
|
||||
use DenormalizerAwareTrait;
|
||||
|
||||
use ObjectToPopulateTrait;
|
||||
|
||||
private ResourceRepository $repository;
|
||||
|
||||
public function __construct(ResourceRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function denormalize($data, string $type, string $format = null, array $context = [])
|
||||
{
|
||||
$resource = $this->extractObjectToPopulate($type, $context);
|
||||
|
||||
if ('accompanying_period_resource' !== ($data['type'] ?? NULL)) {
|
||||
throw new Exception\InvalidArgumentException("the key type must be present in data and set to 'accompanying_period_resource'");
|
||||
}
|
||||
|
||||
if ($resource === NULL && \array_key_exists('id', $data)) {
|
||||
$resource = $this->repository->find($data['id']);
|
||||
|
||||
if (NULL === $resource) {
|
||||
throw new Exception\UnexpectedValueException(sprintf("the resource with".
|
||||
"id %d is not found", $data['id']));
|
||||
}
|
||||
|
||||
// if resource found, available only for read-only
|
||||
if (count($data) > 2) {
|
||||
unset($data['id']);
|
||||
unset($data['type']);
|
||||
throw new Exception\ExtraAttributesException($data);
|
||||
}
|
||||
}
|
||||
|
||||
if ($resource === NULL) {
|
||||
$resource = new Resource();
|
||||
}
|
||||
|
||||
if (\array_key_exists('resource', $data)) {
|
||||
$res = $this->denormalizer->denormalize(
|
||||
$data['resource'],
|
||||
DiscriminatedObjectDenormalizer::TYPE,
|
||||
$format,
|
||||
\array_merge(
|
||||
$context,
|
||||
[
|
||||
DiscriminatedObjectDenormalizer::ALLOWED_TYPES =>
|
||||
[
|
||||
Person::class, ThirdParty::class
|
||||
]
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$resource->setResource($res);
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
|
||||
public function supportsDenormalization($data, string $type, string $format = null)
|
||||
{
|
||||
return $type === Resource::class;
|
||||
}
|
||||
}
|
@@ -25,7 +25,8 @@ use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
|
||||
/**
|
||||
* Serialize a Person entity
|
||||
@@ -33,60 +34,52 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
*/
|
||||
class PersonNormalizer implements
|
||||
NormalizerInterface,
|
||||
NormalizerAwareInterface,
|
||||
DenormalizerInterface
|
||||
NormalizerAwareInterface
|
||||
{
|
||||
|
||||
protected NormalizerInterface $normalizer;
|
||||
|
||||
protected PersonRepository $repository;
|
||||
private ChillEntityRenderExtension $render;
|
||||
|
||||
public const GET_PERSON = 'get_person';
|
||||
|
||||
public function __construct(PersonRepository $repository)
|
||||
public function __construct(ChillEntityRenderExtension $render)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->render = $render;
|
||||
}
|
||||
|
||||
public function normalize($person, string $format = null, array $context = array())
|
||||
{
|
||||
/** @var Person $person */
|
||||
return [
|
||||
'type' => 'person',
|
||||
'id' => $person->getId(),
|
||||
'text' => $this->render->renderString($person),
|
||||
'firstName' => $person->getFirstName(),
|
||||
'lastName' => $person->getLastName(),
|
||||
'birthdate' => $this->normalizer->normalize($person->getBirthdate()),
|
||||
'center' => $this->normalizer->normalize($person->getCenter())
|
||||
'center' => $this->normalizer->normalize($person->getCenter()),
|
||||
'phonenumber' => $person->getPhonenumber(),
|
||||
'mobilenumber' => $person->getMobilenumber(),
|
||||
'altNames' => $this->normalizeAltNames($person->getAltNames())
|
||||
];
|
||||
}
|
||||
|
||||
public function denormalize($data, string $type, string $format = null, array $context = []): Person
|
||||
protected function normalizeAltNames($altNames): array
|
||||
{
|
||||
if ($context[self::GET_PERSON] ?? true) {
|
||||
$id = $data['id'] ?? null;
|
||||
if (NULL === $id) {
|
||||
throw new RuntimeException("missing id into person object");
|
||||
}
|
||||
}
|
||||
/** var Person $person */
|
||||
$person = $this->repository->findOneById($id);
|
||||
$r = [];
|
||||
|
||||
if (NULL === $person) {
|
||||
return UnexpectedValueException("person id not found");
|
||||
foreach ($altNames as $n) {
|
||||
$r[] = [ 'key' => $n->getKey(), 'label' => $n->getLabel() ];
|
||||
}
|
||||
|
||||
return $person;
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return $data instanceof Person;
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, string $type, ?string $format = NULL): bool
|
||||
{
|
||||
return Person::class === $type;
|
||||
}
|
||||
|
||||
public function setNormalizer(NormalizerInterface $normalizer)
|
||||
{
|
||||
|
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
|
||||
class SocialIssueNormalizer implements NormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
private SocialIssueRender $render;
|
||||
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
/**
|
||||
* @param SocialIssueRender $render
|
||||
*/
|
||||
public function __construct(SocialIssueRender $render)
|
||||
{
|
||||
$this->render = $render;
|
||||
}
|
||||
|
||||
|
||||
public function normalize($socialIssue, string $format = null, array $context = [])
|
||||
{
|
||||
/** @var SocialIssue $socialIssue */
|
||||
return [
|
||||
'type' => 'social_issue',
|
||||
'id' => $socialIssue->getId(),
|
||||
'parent_id' => $socialIssue->hasParent() ? $socialIssue->getParent()->getId() : null,
|
||||
'children_ids' => $socialIssue->getChildren()->map(function (SocialIssue $si) { return $si->getId(); }),
|
||||
'title' => $socialIssue->getTitle(),
|
||||
'text' => $this->render->renderString($socialIssue, [])
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return $data instanceof SocialIssue;
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Templating\Entity;
|
||||
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
|
||||
class SocialIssueRender implements ChillEntityRenderInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public const SEPARATOR_KEY = 'default.separator';
|
||||
|
||||
public const DEFAULT_ARGS = [
|
||||
self::SEPARATOR_KEY => ' > ',
|
||||
];
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function supports($entity, array $options): bool
|
||||
{
|
||||
return $entity instanceof SocialIssueRender;
|
||||
}
|
||||
|
||||
public function renderString($socialIssue, array $options): string
|
||||
{
|
||||
/** @var $socialIssue SocialIssue */
|
||||
$options = \array_merge(self::DEFAULT_ARGS, $options);
|
||||
|
||||
$str = $this->translatableStringHelper->localize($socialIssue->getTitle());
|
||||
|
||||
while ($socialIssue->hasParent()) {
|
||||
$socialIssue = $socialIssue->getParent();
|
||||
$str .= $options[self::SEPARATOR_KEY].$this->translatableStringHelper->localize(
|
||||
$socialIssue->getTitle()
|
||||
);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function renderBox($entity, array $options): string
|
||||
{
|
||||
return "renderBox not implemented for social issue";
|
||||
}
|
||||
}
|
@@ -27,11 +27,14 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
|
||||
/**
|
||||
* Test api for AccompanyingCourseControllerTest
|
||||
@@ -40,6 +43,10 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
{
|
||||
protected static EntityManagerInterface $em;
|
||||
|
||||
protected ?int $personId = NULL;
|
||||
|
||||
protected ?AccompanyingPeriod $period = NULL;
|
||||
|
||||
/**
|
||||
* Setup before the first test of this class (see phpunit doc)
|
||||
*/
|
||||
@@ -85,6 +92,310 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
$this->assertEquals(404, $response->getStatusCode(), "Test that the response of rest api has a status code 'not found' (404)");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @dataProvider dataGenerateRandomAccompanyingCourseWithSocialIssue
|
||||
*/
|
||||
public function testAccompanyingCourseAddRemoveSocialIssue(AccompanyingPeriod $period, SocialIssue $si)
|
||||
{
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/socialissue.json', $period->getId()),
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
\json_encode([ 'type' => 'social_issue', 'id' => $si->getId() ])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
|
||||
$data = \json_decode($this->client->getResponse()->getContent(), true);
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertArrayHasKey('type', $data);
|
||||
$this->assertEquals('social_issue', $data['type']);
|
||||
|
||||
|
||||
$this->client->request(
|
||||
Request::METHOD_DELETE,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/socialissue.json', $period->getId()),
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
\json_encode([ 'type' => 'social_issue', 'id' => $si->getId() ])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGenerateRandomRequestorValidData
|
||||
*/
|
||||
public function testCommentWithValidData(AccompanyingPeriod $period, $personId, $thirdPartyId)
|
||||
{
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/comment.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'accompanying_period_comment', 'content' => "this is a text"])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
|
||||
$this->client->request(
|
||||
Request::METHOD_DELETE,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/comment.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'accompanying_period_comment', 'id' => $data['id']])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGenerateRandomRequestorValidData
|
||||
*/
|
||||
public function testResourceWithValidData(AccompanyingPeriod $period, $personId, $thirdPartyId)
|
||||
{
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
// post a person
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/resource.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'accompanying_period_resource', 'resource' => [ 'type' => 'person', 'id' => $personId ]])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertEquals($personId, $data['resource']['id']);
|
||||
|
||||
// check into database
|
||||
$resource = $em->getRepository(Resource::class)
|
||||
->find($data['id']);
|
||||
$this->assertInstanceOf(Resource::class, $resource);
|
||||
$this->assertInstanceOf(Person::class, $resource->getResource());
|
||||
$this->assertEquals($personId, $resource->getResource()->getId());
|
||||
|
||||
// remove the resource
|
||||
$this->client->request(
|
||||
Request::METHOD_DELETE,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/requestor.json', $period->getId()),
|
||||
[],
|
||||
[],
|
||||
[], //server
|
||||
\json_encode([ 'type' => 'accompanying_period_resource', 'id' => $resource->getId()])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
// post a third party
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/resource.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'accompanying_period_resource', 'resource' => [ 'type' => 'thirdparty', 'id' => $thirdPartyId ]])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertEquals($thirdPartyId, $data['resource']['id']);
|
||||
|
||||
// check into database
|
||||
$resource = $em->getRepository(Resource::class)
|
||||
->find($data['id']);
|
||||
$this->assertInstanceOf(Resource::class, $resource);
|
||||
$this->assertInstanceOf(ThirdParty::class, $resource->getResource());
|
||||
$this->assertEquals($thirdPartyId, $resource->getResource()->getId());
|
||||
|
||||
// remove the resource
|
||||
$this->client->request(
|
||||
Request::METHOD_DELETE,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/requestor.json', $period->getId()),
|
||||
[],
|
||||
[],
|
||||
[], //server
|
||||
\json_encode([ 'type' => 'accompanying_period_resource', 'id' => $resource->getId()])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGenerateRandomRequestorValidData
|
||||
*/
|
||||
public function testRequestorWithValidData(AccompanyingPeriod $period, $personId, $thirdPartyId)
|
||||
{
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
// post a person
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/requestor.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertEquals($personId, $data['id']);
|
||||
|
||||
// check into database
|
||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||
->find($period->getId());
|
||||
$this->assertInstanceOf(Person::class, $period->getRequestor());
|
||||
$this->assertEquals($personId, $period->getRequestor()->getId());
|
||||
|
||||
// post a third party
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/requestor.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'thirdparty', 'id' => $thirdPartyId ])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertEquals($thirdPartyId, $data['id']);
|
||||
|
||||
// check into database
|
||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||
->find($period->getId());
|
||||
$this->assertInstanceOf(ThirdParty::class, $period->getRequestor());
|
||||
$this->assertEquals($thirdPartyId, $period->getRequestor()->getId());
|
||||
|
||||
// remove the requestor
|
||||
$this->client->request(
|
||||
Request::METHOD_DELETE,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/requestor.json', $period->getId())
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
// check into database
|
||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||
->find($period->getId());
|
||||
$em->refresh($period);
|
||||
$this->assertNull($period->getRequestor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGenerateNewAccompanyingCourse
|
||||
*/
|
||||
public function testConfirm(AccompanyingPeriod $period)
|
||||
{
|
||||
$this->client->request(
|
||||
Request::METHOD_POST,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d/confirm.json', $period->getId())
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
|
||||
// add period to remove it in tear down
|
||||
$this->period = $period;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @dataProvider dataGenerateRandomAccompanyingCourse
|
||||
*/
|
||||
public function testAccompanyingPeriodPatch(int $personId, AccompanyingPeriod $period)
|
||||
{
|
||||
$initialValueEmergency = $period->isEmergency();
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
$this->client->request(
|
||||
Request::METHOD_PATCH,
|
||||
sprintf('/api/1.0/person/accompanying-course/%d.json', $period->getId()),
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'type' => 'accompanying_period', 'emergency' => !$initialValueEmergency ])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$period = $em->getRepository(AccompanyingPeriod::class)
|
||||
->find($period->getId());
|
||||
$em->refresh($period);
|
||||
$this->assertEquals(!$initialValueEmergency, $period->isEmergency());
|
||||
|
||||
// restore the initial valud
|
||||
$period->setEmergency($initialValueEmergency);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function dataGenerateRandomRequestorValidData(): \Iterator
|
||||
{
|
||||
$dataLength = 2;
|
||||
$maxResults = 100;
|
||||
|
||||
static::bootKernel();
|
||||
$em = static::$container->get(EntityManagerInterface::class);
|
||||
$center = $em->getRepository(Center::class)
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$personIds = $em->createQuery("SELECT p.id FROM ".
|
||||
Person::class." p ".
|
||||
" WHERE p.center = :center")
|
||||
->setParameter('center', $center)
|
||||
->setMaxResults($maxResults)
|
||||
->getScalarResult();
|
||||
|
||||
// create a random order
|
||||
shuffle($personIds);
|
||||
|
||||
$thirdPartyIds = $em->createQuery("SELECT t.id FROM ".
|
||||
ThirdParty::class." t ")
|
||||
->setMaxResults($maxResults)
|
||||
->getScalarResult();
|
||||
|
||||
// create a random order
|
||||
shuffle($thirdPartyIds);
|
||||
|
||||
$i = 0;
|
||||
while ($i <= $dataLength) {
|
||||
$person = $em->getRepository(Person::class)
|
||||
->find(\array_pop($personIds)['id']);
|
||||
|
||||
if (count($person->getAccompanyingPeriods()) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$period = $person->getAccompanyingPeriods()[0];
|
||||
|
||||
yield [$period, \array_pop($personIds)['id'], \array_pop($thirdPartyIds)['id'] ];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @dataProvider dataGenerateRandomAccompanyingCourse
|
||||
@@ -97,7 +408,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'id' => $personId ])
|
||||
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
@@ -128,7 +439,7 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
[], // parameters
|
||||
[], // files
|
||||
[], // server parameters
|
||||
\json_encode([ 'id' => $personId ])
|
||||
\json_encode([ 'type' => 'person', 'id' => $personId ])
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
$data = \json_decode($response->getContent(), true);
|
||||
@@ -148,25 +459,79 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
// remove participation created during test 'testAccompanyingCourseAddParticipation'
|
||||
// and if the test could not remove it
|
||||
|
||||
$testAddParticipationName = 'testAccompanyingCourseAddParticipation';
|
||||
|
||||
if ($testAddParticipationName !== \substr($this->getName(), 0, \strlen($testAddParticipationName))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$em = static::$container->get(EntityManagerInterface::class);
|
||||
|
||||
$participation = $em
|
||||
->getRepository(AccompanyingPeriodParticipation::class)
|
||||
->findOneBy(['person' => $this->personId, 'accompanyingPeriod' => $this->period])
|
||||
;
|
||||
// remove participation if set
|
||||
if ($this->personId && $this->period) {
|
||||
$participation = $em
|
||||
->getRepository(AccompanyingPeriodParticipation::class)
|
||||
->findOneBy(['person' => $this->personId, 'accompanyingPeriod' => $this->period])
|
||||
;
|
||||
|
||||
if (NULL !== $participation) {
|
||||
$em->remove($participation);
|
||||
$em->flush();
|
||||
if (NULL !== $participation) {
|
||||
$em->remove($participation);
|
||||
$em->flush();
|
||||
}
|
||||
$this->personId = NULL;
|
||||
$this->period = NULL;
|
||||
} elseif ($this->period) {
|
||||
$period = $em
|
||||
->getRepository(AccompanyingPeriod::class)
|
||||
->find($this->period->getId()) ;
|
||||
|
||||
if ($period !== NULL) {
|
||||
$em->remove($period);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
$this->period = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function dataGenerateRandomAccompanyingCourseWithSocialIssue()
|
||||
{
|
||||
// note about max result for person query, and maxGenerated:
|
||||
//
|
||||
// in the final loop, an id is popped out of the personIds array twice:
|
||||
//
|
||||
// * one for getting the person, which will in turn provide his accompanying period;
|
||||
// * one for getting the personId to populate to the data manager
|
||||
//
|
||||
// Ensure to keep always $maxGenerated to the double of $maxResults. x8 is a good compromize :)
|
||||
$maxGenerated = 3;
|
||||
$maxResults = $maxGenerated * 8;
|
||||
|
||||
static::bootKernel();
|
||||
$em = static::$container->get(EntityManagerInterface::class);
|
||||
$center = $em->getRepository(Center::class)
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$personIds = $em->createQuery("SELECT p.id FROM ".
|
||||
Person::class." p ".
|
||||
" WHERE p.center = :center")
|
||||
->setParameter('center', $center)
|
||||
->setMaxResults($maxResults)
|
||||
->getScalarResult();
|
||||
|
||||
// create a random order
|
||||
shuffle($personIds);
|
||||
|
||||
$socialIssues = $em->createQuery("SELECT s FROM ".
|
||||
SocialIssue::class." s ")
|
||||
->setMaxResults(10)
|
||||
->getResult();
|
||||
|
||||
$nbGenerated = 0;
|
||||
while ($nbGenerated < $maxGenerated) {
|
||||
$id = \array_pop($personIds)["id"];
|
||||
|
||||
$person = $em->getRepository(Person::class)
|
||||
->find($id);
|
||||
$periods = $person->getAccompanyingPeriods();
|
||||
|
||||
yield [$periods[\array_rand($periods)], $socialIssues[\array_rand($socialIssues)] ];
|
||||
|
||||
$nbGenerated++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,4 +576,39 @@ class AccompanyingCourseApiControllerTest extends WebTestCase
|
||||
$nbGenerated++;
|
||||
}
|
||||
}
|
||||
|
||||
public function dataGenerateNewAccompanyingCourse()
|
||||
{
|
||||
self::bootKernel();
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
$period = new AccompanyingPeriod(new \DateTime('1 week ago'));
|
||||
$user = $em->getRepository(User::class)
|
||||
->findOneByUsernameCanonical('center a_social');
|
||||
$period->setCreatedBy($user);
|
||||
//$period->setCreatedAt(new \DateTime('yesterday'));
|
||||
|
||||
$center = $em->getRepository(Center::class)
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$personIds = $em->createQuery("SELECT p.id FROM ".
|
||||
Person::class." p ".
|
||||
" WHERE p.center = :center")
|
||||
->setParameter('center', $center)
|
||||
->setMaxResults(100)
|
||||
->getScalarResult();
|
||||
|
||||
// create a random order
|
||||
shuffle($personIds);
|
||||
|
||||
for ($i = 0; $i<2; $i++) {
|
||||
$person = $em->getRepository(Person::class)->find(\array_pop($personIds));
|
||||
$period->addPerson($person);
|
||||
}
|
||||
|
||||
$em->persist($period);
|
||||
$em->flush();
|
||||
|
||||
yield [ $period ];
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Controller;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class AccompanyingCourseControllerTest extends WebTestCase
|
||||
{
|
||||
use PrepareClientTrait;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
self::bootKernel();
|
||||
$this->client = $this->getClientAuthenticated();
|
||||
}
|
||||
|
||||
public function testNewWithoutUsers()
|
||||
{
|
||||
$this->client->request('GET', '/fr/person/parcours/new');
|
||||
|
||||
$this->assertResponseRedirects();
|
||||
$location = $this->client->getResponse()->headers->get('Location');
|
||||
|
||||
$this->assertEquals(1, \preg_match("|^\/[^\/]+\/parcours/([\d]+)/show$|", $location));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataGenerateRandomUsers
|
||||
*/
|
||||
public function testWithNewUsers($personId0, $personId1)
|
||||
{
|
||||
$this->client->request('GET', '/fr/person/parcours/new', [
|
||||
'person_id' => [
|
||||
$personId0,
|
||||
$personId1
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertResponseRedirects();
|
||||
$location = $this->client->getResponse()->headers->get('Location');
|
||||
$matches = [];
|
||||
|
||||
$this->assertEquals(1, \preg_match("|^\/[^\/]+\/parcours/([\d]+)/show$|", $location, $matches));
|
||||
$id = $matches[1];
|
||||
|
||||
$period = self::$container->get(EntityManagerInterface::class)
|
||||
->getRepository(AccompanyingPeriod::class)
|
||||
->find($id);
|
||||
|
||||
$this->assertNotNull($period);
|
||||
|
||||
$this->assertEquals(2, count($period->getParticipations()));
|
||||
}
|
||||
|
||||
public function dataGenerateRandomUsers(): \Iterator
|
||||
{
|
||||
self::bootKernel();
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
$period = new AccompanyingPeriod(new \DateTime('1 week ago'));
|
||||
$user = $em->getRepository(User::class)
|
||||
->findOneByUsernameCanonical('center a_social');
|
||||
$period->setCreatedBy($user);
|
||||
//$period->setCreatedAt(new \DateTime('yesterday'));
|
||||
|
||||
$center = $em->getRepository(Center::class)
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$personIds = $em->createQuery("SELECT p.id FROM ".
|
||||
Person::class." p ".
|
||||
" WHERE p.center = :center")
|
||||
->setParameter('center', $center)
|
||||
->setMaxResults(100)
|
||||
->getScalarResult();
|
||||
|
||||
yield [ \array_pop($personIds), \array_pop($personIds) ];
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -11,7 +11,7 @@ class PersonDuplicateControllerViewTest extends WebTestCase
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$this->em = static::$kernel->getContainer()
|
||||
$this->em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
$center = $this->em->getRepository('ChillMainBundle:Center')
|
||||
|
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||
|
||||
class SocialIssueApiControllerTest extends WebTestCase
|
||||
{
|
||||
use PrepareClientTrait;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
public function testList(): array
|
||||
{
|
||||
$client = $this->getClientAuthenticated();
|
||||
$client->request(Request::METHOD_GET, '/api/1.0/person/social-work/social-issue.json');
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$data = \json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertGreaterThan(0, $data['count']);
|
||||
$this->assertGreaterThan(0, count($data['results']));
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testList
|
||||
*/
|
||||
public function testItem(array $data): void
|
||||
{
|
||||
$socialIssues = $data['results'];
|
||||
shuffle($socialIssues);
|
||||
$socialIssue = \array_pop($socialIssues);
|
||||
|
||||
|
||||
$client = $this->getClientAuthenticated();
|
||||
$client->request(Request::METHOD_GET, sprintf('/api/1.0/person/social-work/social-issue/%d.json', $socialIssue['id']));
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$data = \json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertArrayHasKey('id', $data);
|
||||
$this->assertArrayHasKey('type', $data);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Entity\AccompanyingPeriod;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
|
||||
class ResourceTest extends TestCase
|
||||
{
|
||||
public function testSetResource()
|
||||
{
|
||||
$person = new Person();
|
||||
$thirdParty = new ThirdParty();
|
||||
|
||||
$resource = new Resource();
|
||||
|
||||
$resource->setResource($person);
|
||||
|
||||
$this->assertSame($person, $resource->getResource());
|
||||
$this->assertNull($resource->getThirdParty());
|
||||
|
||||
$resource->setResource($thirdParty);
|
||||
|
||||
$this->assertSame($thirdParty, $resource->getResource());
|
||||
$this->assertNull($resource->getPerson());
|
||||
|
||||
// we repeat adding a person, to ensure that third party is
|
||||
// well reset
|
||||
$resource->setResource($person);
|
||||
$this->assertSame($person, $resource->getResource());
|
||||
$this->assertNull($resource->getThirdParty());
|
||||
|
||||
$resource->setResource(null);
|
||||
$this->assertNull($resource->getThirdParty());
|
||||
$this->assertNull($resource->getPerson());
|
||||
$this->assertNull($resource->getResource());
|
||||
}
|
||||
}
|
@@ -24,6 +24,8 @@ namespace Chill\PersonBundle\Tests\Entity;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
|
||||
class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
@@ -104,4 +106,56 @@ class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase
|
||||
$participation = $period->getOpenParticipationContainsPerson($person);
|
||||
$this->assertNull($participation);
|
||||
}
|
||||
|
||||
public function testRequestor()
|
||||
{
|
||||
$period = new AccompanyingPeriod(new \DateTime());
|
||||
$person = new Person();
|
||||
$thirdParty = new ThirdParty();
|
||||
|
||||
$this->assertNull($period->getRequestorThirdParty());
|
||||
$this->assertNull($period->getRequestorPerson());
|
||||
$this->assertNull($period->getRequestor());
|
||||
|
||||
$period->setRequestor($person);
|
||||
$this->assertNull($period->getRequestorThirdParty());
|
||||
$this->assertSame($person, $period->getRequestorPerson());
|
||||
$this->assertSame($person, $period->getRequestor());
|
||||
|
||||
$period->setRequestor($thirdParty);
|
||||
$this->assertNull($period->getRequestorPerson());
|
||||
$this->assertSame($thirdParty, $period->getRequestorThirdParty());
|
||||
$this->assertSame($thirdParty, $period->getRequestor());
|
||||
|
||||
$period->setRequestor(NULL);
|
||||
$this->assertNull($period->getRequestorThirdParty());
|
||||
$this->assertNull($period->getRequestorPerson());
|
||||
$this->assertNull($period->getRequestor());
|
||||
}
|
||||
|
||||
public function testInitialComment()
|
||||
{
|
||||
$period = new AccompanyingPeriod(new \DateTime());
|
||||
$comment = new Comment();
|
||||
$replacingComment = new Comment();
|
||||
|
||||
$period->setInitialComment(NULL);
|
||||
$this->assertNull($period->getInitialComment());
|
||||
|
||||
$period->setInitialComment($comment);
|
||||
$this->assertSame($period->getInitialComment(), $comment);
|
||||
$this->assertSame($period, $comment->getAccompanyingPeriod());
|
||||
$this->assertEquals(0, count($period->getComments()), "The initial comment should not appears in the list of comments");
|
||||
|
||||
$period->setInitialComment($replacingComment);
|
||||
$this->assertSame($period->getInitialComment(), $replacingComment);
|
||||
$this->assertSame($period, $replacingComment->getAccompanyingPeriod());
|
||||
$this->assertEquals(0, count($period->getComments()), "The initial comment should not appears in the list of comments");
|
||||
$this->assertNull($comment->getAccompanyingPeriod());
|
||||
|
||||
$period->setInitialComment(NULL);
|
||||
$this->assertNull($period->getInitialComment());
|
||||
$this->assertNull($replacingComment->getAccompanyingPeriod());
|
||||
$this->assertEquals(0, count($period->getComments()), "The initial comment should not appears in the list of comments");
|
||||
}
|
||||
}
|
||||
|
@@ -38,9 +38,7 @@ class AgeAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
$this->aggregator = $container->get('chill.person.export.aggregator_age');
|
||||
$this->aggregator = static::$container->get('chill.person.export.aggregator_age');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
@@ -63,7 +61,7 @@ class AgeAggregatorTest extends AbstractAggregatorTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
||||
|
@@ -37,9 +37,7 @@ class GenderAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
$this->aggregator = $container->get('chill.person.export.aggregator_gender');
|
||||
$this->aggregator = static::$container->get('chill.person.export.aggregator_gender');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
@@ -60,7 +58,7 @@ class GenderAggregatorTest extends AbstractAggregatorTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
||||
|
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
namespace Chill\PersonBundle\Tests\Export\Aggregator;
|
||||
|
||||
require_once '/home/julien/dev/chill-dev/vendor/chill-project/main/Test/Export/AbstractAggregatorTest.php';
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,7 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class NationalityAggregator extends AbstractAggregatorTest
|
||||
class NationalityAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
/**
|
||||
*
|
||||
@@ -37,9 +36,7 @@ class NationalityAggregator extends AbstractAggregatorTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
$this->aggregator = $container->get('chill.person.export.aggregator_nationality');
|
||||
$this->aggregator = static::$container->get('chill.person.export.aggregator_nationality');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
@@ -61,7 +58,7 @@ class NationalityAggregator extends AbstractAggregatorTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
@@ -36,10 +36,7 @@ class CountPersonTest extends AbstractExportTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
/* @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$this->export = $container->get('chill.person.export.export_count_person');
|
||||
$this->export = static::$container->get('chill.person.export.export_count_person');
|
||||
}
|
||||
|
||||
|
||||
|
@@ -40,10 +40,7 @@ class ListPersonTest extends AbstractExportTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
/* @var $container \Symfony\Component\DependencyInjection\ContainerInterface */
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$this->export = $container->get('chill.person.export.list_person');
|
||||
$this->export = static::$container->get('chill.person.export.list_person');
|
||||
|
||||
// add a fake request with a default locale (used in translatable string)
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
@@ -51,7 +48,7 @@ class ListPersonTest extends AbstractExportTest
|
||||
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
$request->getLocale()->willReturn('fr');
|
||||
|
||||
$container->get('request_stack')
|
||||
static::$container->get('request_stack')
|
||||
->push($request->reveal());
|
||||
}
|
||||
|
||||
|
@@ -36,10 +36,8 @@ class AccompanyingPeriodFilterTest extends AbstractFilterTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
try {
|
||||
$this->filter = $container->get('chill.person.export.filter_accompanying_period');
|
||||
$this->filter = static::$container->get('chill.person.export.filter_accompanying_period');
|
||||
} catch (ServiceNotFoundException $e) {
|
||||
$this->markTestSkipped("The current configuration does not use accompanying_periods");
|
||||
}
|
||||
@@ -67,7 +65,7 @@ class AccompanyingPeriodFilterTest extends AbstractFilterTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
||||
|
@@ -36,9 +36,7 @@ class BirthdayFilterTest extends AbstractFilterTest
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
$this->filter = $container->get('chill.person.export.filter_birthdate');
|
||||
$this->filter = static::$container->get('chill.person.export.filter_birthdate');
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +61,7 @@ class BirthdayFilterTest extends AbstractFilterTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
||||
|
@@ -43,9 +43,7 @@ class GenderFilterTest extends AbstractFilterTest
|
||||
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
$request->getLocale()->willReturn('fr');
|
||||
|
||||
$container = static::$kernel->getContainer();
|
||||
|
||||
$this->filter = $container->get('chill.person.export.filter_gender');
|
||||
$this->filter = static::$container->get('chill.person.export.filter_gender');
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +73,7 @@ class GenderFilterTest extends AbstractFilterTest
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
$em = static::$kernel->getContainer()
|
||||
$em = static::$container
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
return array(
|
||||
|
@@ -60,7 +60,7 @@ class PersonVoterTest extends KernelTestCase
|
||||
public function setUp()
|
||||
{
|
||||
static::bootKernel();
|
||||
$this->voter = static::$kernel->getContainer()
|
||||
$this->voter = static::$container
|
||||
->get('chill.person.security.authorization.person');
|
||||
$this->prophet = new \Prophecy\Prophet();
|
||||
}
|
||||
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Workflows;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
class AccompanyingPeriodLifecycle extends KernelTestCase
|
||||
{
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
public function testConfirm()
|
||||
{
|
||||
$registry = self::$container->get(Registry::class);
|
||||
$period = new AccompanyingPeriod(new \DateTime('now'));
|
||||
$workflow = $registry->get($period);
|
||||
|
||||
$this->assertArrayHasKey('DRAFT', $workflow->getMarking($period)->getPlaces());
|
||||
$this->assertTrue($workflow->can($period, 'confirm'));
|
||||
}
|
||||
|
||||
}
|
703
src/Bundle/ChillPersonBundle/chill.api.specs.yaml
Normal file
703
src/Bundle/ChillPersonBundle/chill.api.specs.yaml
Normal file
@@ -0,0 +1,703 @@
|
||||
components:
|
||||
schemas:
|
||||
# should go to main
|
||||
Date:
|
||||
type: object
|
||||
properties:
|
||||
datetime:
|
||||
type: string
|
||||
format: date-time
|
||||
Scope:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- scope
|
||||
name:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
fr: Social
|
||||
ScopeById:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- scope
|
||||
required:
|
||||
- id
|
||||
- scope
|
||||
|
||||
# ok to stay here
|
||||
Person:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
firstName:
|
||||
type: string
|
||||
lastName:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
description: a canonical representation for the person name
|
||||
birthdate:
|
||||
$ref: '#/components/schemas/Date'
|
||||
phonenumber:
|
||||
type: string
|
||||
mobilenumber:
|
||||
type: string
|
||||
PersonById:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'person'
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
# should go to third party
|
||||
ThirdParty:
|
||||
type: object
|
||||
properties:
|
||||
text:
|
||||
type: string
|
||||
ThirdPartyById:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'thirdparty'
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
|
||||
# ok to stay here
|
||||
AccompanyingPeriod:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- accompanying_period
|
||||
id:
|
||||
type: integer
|
||||
requestorAnonymous:
|
||||
type: boolean
|
||||
Resource:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'accompanying_period_resource'
|
||||
readOnly: true
|
||||
id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
resource:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/PersonById'
|
||||
- $ref: '#/components/schemas/ThirdPartyById'
|
||||
ResourceById:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'accompanying_period_resource'
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
Comment:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'accompanying_period_comment'
|
||||
readOnly: true
|
||||
id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
content:
|
||||
type: string
|
||||
CommentById:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'accompanying_period_comment'
|
||||
required:
|
||||
- id
|
||||
- type
|
||||
SocialIssue:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- 'social_issue'
|
||||
parent_id:
|
||||
type: integer
|
||||
readOnly: true
|
||||
children_ids:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
readOnly: true
|
||||
title:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
fr: Accompagnement Social Adulte
|
||||
readOnly: true
|
||||
text:
|
||||
type: string
|
||||
readOnly: true
|
||||
|
||||
paths:
|
||||
/1.0/person/social-work/social-issue.json:
|
||||
get:
|
||||
tags:
|
||||
- social-issue
|
||||
summary: Return a list of social work
|
||||
responses:
|
||||
200:
|
||||
description: "ok"
|
||||
/1.0/person/social-work/social-issue/{id}.json:
|
||||
get:
|
||||
tags:
|
||||
- social-issue
|
||||
summary: Return a social issue by id
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The social issue's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
200:
|
||||
description: "ok"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SocialIssue'
|
||||
404:
|
||||
description: "not found"
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
/1.0/person/accompanying-course/{id}.json:
|
||||
get:
|
||||
tags:
|
||||
- person
|
||||
summary: "Return the description for an accompanying course (accompanying period)"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
patch:
|
||||
tags:
|
||||
- person
|
||||
summary: "Alter an accompanying course (accompanying period)"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "An accompanying period"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AccompanyingPeriod'
|
||||
examples:
|
||||
Set the requestor as anonymous:
|
||||
value:
|
||||
type: accompanying_period
|
||||
id: 12345
|
||||
requestorAnonymous: true
|
||||
Adding an initial comment:
|
||||
value:
|
||||
type: accompanying_period
|
||||
id: 2668,
|
||||
initialComment:
|
||||
type: accompanying_period_comment
|
||||
content: >
|
||||
This is my an initial comment.
|
||||
|
||||
Say hello to the new "parcours"!
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
/1.0/person/accompanying-course/{id}/requestor.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a requestor to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A person or thirdparty"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/PersonById'
|
||||
- $ref: '#/components/schemas/ThirdPartyById'
|
||||
examples:
|
||||
add person with id 50:
|
||||
summary: "a person with id 50"
|
||||
value:
|
||||
type: person
|
||||
id: 50
|
||||
add thirdparty with id 100:
|
||||
summary: "a third party with id 100"
|
||||
value:
|
||||
type: thirdparty
|
||||
id: 100
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the requestor for the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/participation.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a participant to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A person"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PersonById'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the participant for the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A person"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PersonById'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/resource.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a resource to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A resource"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Resource'
|
||||
examples:
|
||||
add person with id 50:
|
||||
summary: "a person with id 50"
|
||||
value:
|
||||
type: accompanying_period_resource
|
||||
resource:
|
||||
type: person
|
||||
id: 50
|
||||
add thirdparty with id 100:
|
||||
summary: "a third party with id 100"
|
||||
value:
|
||||
type: accompanying_period_resource
|
||||
resource:
|
||||
type: thirdparty
|
||||
id: 100
|
||||
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the resource"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A resource"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ResourceById'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/comment.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a comment to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A comment"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Comment'
|
||||
examples:
|
||||
a single comment:
|
||||
summary: "a simple comment"
|
||||
value:
|
||||
type: accompanying_period_comment
|
||||
content: |
|
||||
This is a funny comment I would like to share with you.
|
||||
|
||||
Thank you for reading this !
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the comment"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A comment"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CommentById'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/scope.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a scope to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A comment"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Scope'
|
||||
examples:
|
||||
add a scope:
|
||||
value:
|
||||
type: scope
|
||||
id: 5
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the scope"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A scope with his id"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScopeById'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/socialissue.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: "Add a social issue to the accompanying course"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A social issue by id"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SocialIssue'
|
||||
examples:
|
||||
add a social issue:
|
||||
value:
|
||||
type: social_issue
|
||||
id: 5
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
delete:
|
||||
tags:
|
||||
- person
|
||||
summary: "Remove the social issue"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
description: "A social issue with his id"
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SocialIssue'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/person/accompanying-course/{id}/confirm.json:
|
||||
post:
|
||||
tags:
|
||||
- person
|
||||
summary: confirm an accompanying course
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The accompanying period's id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
400:
|
||||
description: "transition cannot be applyed"
|
@@ -1,11 +1,17 @@
|
||||
parameters:
|
||||
# cl_chill_person.example.class: Chill\PersonBundle\Example
|
||||
|
||||
services:
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\PersonBundle\Serializer\Normalizer\:
|
||||
resource: '../Serializer/Normalizer/'
|
||||
autowire: true
|
||||
tags:
|
||||
- { name: 'serializer.normalizer', priority: 64 }
|
||||
|
||||
chill.person.form.type.select2maritalstatus:
|
||||
class: Chill\PersonBundle\Form\Type\Select2MaritalStatusType
|
||||
arguments:
|
||||
@@ -38,5 +44,7 @@ services:
|
||||
- { name: validator.constraint_validator, alias: birthdate_not_before }
|
||||
|
||||
Chill\PersonBundle\Repository\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Repository/'
|
||||
tags: ['doctrine.repository_service']
|
||||
|
@@ -51,4 +51,5 @@ services:
|
||||
arguments:
|
||||
$eventDispatcher: '@Symfony\Contracts\EventDispatcher\EventDispatcherInterface'
|
||||
$validator: '@Symfony\Component\Validator\Validator\ValidatorInterface'
|
||||
$registry: '@Symfony\Component\Workflow\Registry'
|
||||
tags: ['controller.service_arguments']
|
||||
|
@@ -1,5 +1,4 @@
|
||||
services:
|
||||
|
||||
chill.person.repository.person:
|
||||
class: Chill\PersonBundle\Repository\PersonRepository
|
||||
autowire: true
|
||||
|
@@ -1,15 +1,10 @@
|
||||
---
|
||||
services:
|
||||
Chill\PersonBundle\Serializer\Normalizer\PersonNormalizer:
|
||||
arguments:
|
||||
$repository: '@Chill\PersonBundle\Repository\PersonRepository'
|
||||
# note: normalizers are loaded from ../services.yaml
|
||||
|
||||
Chill\PersonBundle\Serializer\Normalizer\:
|
||||
autowire: true
|
||||
resource: '../../Serializer/Normalizer'
|
||||
tags:
|
||||
- { name: 'serializer.normalizer', priority: 64 }
|
||||
|
||||
Chill\PersonBundle\Serializer\Normalizer\AccompanyingPeriodNormalizer:
|
||||
tags:
|
||||
- { name: 'serializer.normalizer', priority: 64 }
|
||||
|
||||
Chill\PersonBundle\Serializer\Normalizer\AccompanyingPeriodParticipationNormalizer:
|
||||
tags:
|
||||
- { name: 'serializer.normalizer', priority: 64 }
|
||||
|
@@ -1,12 +1,19 @@
|
||||
services:
|
||||
Chill\PersonBundle\Templating\Entity\:
|
||||
resource: '../../Templating/Entity'
|
||||
tags:
|
||||
- 'chill.render_entity'
|
||||
|
||||
Chill\PersonBundle\Templating\Entity\PersonRender:
|
||||
arguments:
|
||||
$configAltNamesHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper'
|
||||
tags:
|
||||
- 'chill.render_entity'
|
||||
|
||||
|
||||
Chill\PersonBundle\Templating\Entity\ClosingMotiveRender:
|
||||
arguments:
|
||||
$translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper'
|
||||
tags:
|
||||
- 'chill.render_entity'
|
||||
|
||||
Chill\PersonBundle\Templating\Entity\SocialIssueRender:
|
||||
arguments:
|
||||
$translatableStringHelper: '@Chill\MainBundle\Templating\TranslatableStringHelper'
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add a link between social issues and accompanying periods
|
||||
*/
|
||||
final class Version20210518075908 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add a link between social issue and accompanying period';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE chill_person_accompanying_period_social_issues (accompanyingperiod_id INT NOT NULL, socialissue_id INT NOT NULL, PRIMARY KEY(accompanyingperiod_id, socialissue_id))');
|
||||
$this->addSql('CREATE INDEX IDX_CAFE078F550B0C53 ON chill_person_accompanying_period_social_issues (accompanyingperiod_id)');
|
||||
$this->addSql('CREATE INDEX IDX_CAFE078FA549916C ON chill_person_accompanying_period_social_issues (socialissue_id)');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_social_issues ADD CONSTRAINT FK_CAFE078F550B0C53 FOREIGN KEY (accompanyingperiod_id) REFERENCES chill_person_accompanying_period (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_social_issues ADD CONSTRAINT FK_CAFE078FA549916C FOREIGN KEY (socialissue_id) REFERENCES chill_person_social_issue (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE chill_person_accompanying_period_social_issues');
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add a column "initial comment" in accompanying period
|
||||
*/
|
||||
final class Version20210518162439 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add a column "initial comment" in accompanying period';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD initialComment_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A8683111D50B FOREIGN KEY (initialComment_id) REFERENCES chill_person_accompanying_period_comment (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_E260A8683111D50B ON chill_person_accompanying_period (initialComment_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP initialComment_id');
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add updatedAt, updatedBy, createdAt on accompanying period
|
||||
*/
|
||||
final class Version20210519204938 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add updatedAt, updatedBy, createdAt on accompanying period';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD updatedBy_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A86865FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_E260A86865FF1AEC ON chill_person_accompanying_period (updatedBy_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP createdAt');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP updatedAt');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP updatedBy_id');
|
||||
}
|
||||
}
|
@@ -153,6 +153,7 @@ Update accompanying period: Mettre à jour une période d'accompagnement
|
||||
Any accompanying periods are open: Aucune période d'accompagnement ouverte
|
||||
An accompanying period is open: Une période d'accompagnement est ouverte
|
||||
Accompanying period list: Périodes d'accompagnement
|
||||
New accompanying course: Nouveau parcours d'accompagnement
|
||||
Choose a motive: Motif de fermeture
|
||||
Re-open accompanying period: Ré-ouvrir
|
||||
Re-Open a period: Ré-ouvrir
|
||||
@@ -162,6 +163,14 @@ Pediod closing form is not valid: Le formulaire n'est pas valide
|
||||
Accompanying user: Accompagnant
|
||||
No accompanying user: Aucun accompagnant
|
||||
No data given: Pas d'information
|
||||
Create an accompanying course: Créer un parcours
|
||||
This accompanying course is still a draft: Ce parcours est à l'état brouillon
|
||||
Associated peoples: Usagers concernés
|
||||
Resources: Interlocuteurs privilégiés
|
||||
Social actions: Actions d'accompagnement
|
||||
Last events on accompanying course: Dernières actions de suivi
|
||||
Edit & activate accompanying course: Modifier et valider
|
||||
|
||||
# pickAPersonType
|
||||
Pick a person: Choisir une personne
|
||||
|
||||
|
Reference in New Issue
Block a user