Compare commits

..

8 Commits

Author SHA1 Message Date
Pol Dellaiera
cea8308aea Simplify configuration by using regexes. 2021-06-08 17:44:20 +02:00
Pol Dellaiera
dcf896ef52 Remove obsolete file. 2021-06-08 13:59:28 +02:00
Pol Dellaiera
39dcc59a0c Fix PHP syntax errors. 2021-06-08 13:59:06 +02:00
Pol Dellaiera
a7af30c378 Add License. 2021-06-08 13:58:54 +02:00
Pol Dellaiera
9c8d813417 Add Psalm configuration. 2021-06-08 13:58:48 +02:00
Pol Dellaiera
7169b4bfbb Add PHPStan configuration. 2021-06-08 13:58:40 +02:00
Pol Dellaiera
07c34d0860 Add Grumphp configuration. 2021-06-08 13:58:10 +02:00
Pol Dellaiera
ee40e1ffd2 Add drupol/php-conventions and normalize. 2021-06-08 13:56:53 +02:00
1327 changed files with 57259 additions and 55180 deletions

View File

@@ -5,13 +5,11 @@ image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
cache: cache:
paths: paths:
- tests/app/vendor/ - tests/app/vendor/
- .composer
before_script: before_script:
# add extensions to postgres # add extensions to postgres
- PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER -h db -c "CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS pg_trgm;" - PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER -h db -c "CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS pg_trgm;"
# Install and run Composer # Install and run Composer
- mkdir -p $COMPOSER_HOME
- curl -sS https://getcomposer.org/installer | php - curl -sS https://getcomposer.org/installer | php
- php -d memory_limit=2G composer.phar install - php -d memory_limit=2G composer.phar install
- php tests/app/bin/console doctrine:migrations:migrate -n - php tests/app/bin/console doctrine:migrations:migrate -n
@@ -36,10 +34,6 @@ variables:
REDIS_HOST: redis REDIS_HOST: redis
REDIS_PORT: 6379 REDIS_PORT: 6379
REDIS_URL: redis://redis:6379 REDIS_URL: redis://redis:6379
# change vendor dir to make the app install into tests/apps
COMPOSER_VENDOR_DIR: tests/app/vendor
# cache some composer data
COMPOSER_HOME: .composer
# Run our tests # Run our tests

View File

@@ -629,12 +629,12 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
chill-bundles <one line to give the program's name and a brief idea of what it does.>
Copyright (C) 2021 Chill Project Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Affero General Public License as published by
by the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,

View File

@@ -9,18 +9,17 @@
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"require": { "require": {
"champs-libres/async-uploader-bundle": "dev-sf4", "champs-libres/async-uploader-bundle": "dev-sf4",
"champs-libres/wopi-bundle": "dev-master",
"composer/package-versions-deprecated": "^1.10", "composer/package-versions-deprecated": "^1.10",
"doctrine/doctrine-bundle": "^2.1", "doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7", "doctrine/orm": "^2.7",
"drupol/php-conventions": "^5.0",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"graylog2/gelf-php": "^1.5", "graylog2/gelf-php": "^1.5",
"knplabs/knp-menu": "^3.1", "knplabs/knp-menu": "^3.1",
"knplabs/knp-menu-bundle": "^3.0", "knplabs/knp-menu-bundle": "^3.0",
"knplabs/knp-time-bundle": "^1.12", "knplabs/knp-time-bundle": "^1.12",
"league/csv": "^9.7.1", "league/csv": "^9.6",
"nyholm/psr7": "^1.4",
"phpoffice/phpspreadsheet": "^1.16", "phpoffice/phpspreadsheet": "^1.16",
"sensio/framework-extra-bundle": "^5.5", "sensio/framework-extra-bundle": "^5.5",
"symfony/asset": "4.*", "symfony/asset": "4.*",
@@ -77,11 +76,7 @@
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle", "Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle", "Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle", "Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle", "Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle"
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
"Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src"
} }
}, },
"autoload-dev": { "autoload-dev": {
@@ -89,8 +84,6 @@
"App\\": "tests/app/src/" "App\\": "tests/app/src/"
} }
}, },
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
"cache:clear": "symfony-cmd", "cache:clear": "symfony-cmd",

View File

@@ -14,7 +14,7 @@ use Chill\MainBundle\Export\FormatterInterface;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
/** /**
* *
* *
* @author Julien Fastré <julien.fastre@champs-libres.coop> * @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
@@ -25,94 +25,95 @@ class CountPerson implements ExportInterface
* @var EntityManagerInterface * @var EntityManagerInterface
*/ */
protected $entityManager; protected $entityManager;
public function __construct( public function __construct(
EntityManagerInterface $em EntityManagerInterface $em
) )
{ {
$this->entityManager = $em; $this->entityManager = $em;
} }
public function getType() public function getType()
{ {
return Declarations::PERSON_TYPE; return Declarations::PERSON_TYPE;
} }
public function getDescription() public function getDescription()
{ {
return "Count peoples by various parameters."; return "Count peoples by various parameters.";
} }
public function getTitle() public function getTitle()
{ {
return "Count peoples"; return "Count peoples";
} }
public function requiredRole() public function requiredRole()
{ {
return new Role(PersonVoter::STATS); return new Role(PersonVoter::STATS);
} }
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array()) public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
{ {
// we gather all center the user choose. // we gather all center the user choose.
$centers = array_map(function($el) { return $el['center']; }, $acl); $centers = array_map(function($el) { return $el['center']; }, $acl);
$qb = $this->entityManager->createQueryBuilder(); $qb = $this->entityManager->createQueryBuilder();
$qb->select('COUNT(person.id) AS export_result') $qb->select('COUNT(person.id) AS export_result')
->from('ChillPersonBundle:Person', 'person') ->from('ChillPersonBundle:Person', 'person')
->join('person.center', 'center') ->join('person.center', 'center')
->andWhere('center IN (:authorized_centers)') ->andWhere('center IN (:authorized_centers)')
->setParameter('authorized_centers', $centers); ->setParameter('authorized_centers', $centers);
; ;
return $qb; return $qb;
} }
public function getResult($qb, $data) public function getResult($qb, $data)
{ {
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR); return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
} }
public function getQueryKeys($data) public function getQueryKeys($data)
{ {
// this array match the result keys in the query. We have only // this array match the result keys in the query. We have only
// one column. // one column.
return array('export_result'); return array('export_result');
} }
public function getLabels($key, array $values, $data) public function getLabels($key, array $values, $data)
{ {
// the Closure which will be executed by the formatter. // the Closure which will be executed by the formatter.
return function($value) { return function($value) {
switch($value) { switch($value) {
case '_header': case '_header':
// we have to process specifically the '_header' string, // we have to process specifically the '_header' string,
// which will be used by the formatter to show a column title // which will be used by the formatter to show a column title
return $this->getTitle(); return $this->getTitle();
default: default:
// for all value, we do not process them and return them // for all value, we do not process them and return them
// immediatly // immediatly
return $value; return $value;
};
}; };
} }
public function getAllowedFormattersTypes() public function getAllowedFormattersTypes()
{ {
return array(FormatterInterface::TYPE_TABULAR); return array(FormatterInterface::TYPE_TABULAR);
} }
public function buildForm(FormBuilderInterface $builder) { public function buildForm(FormBuilderInterface $builder) {
// this export does not add any form // this export does not add any form
} }
public function supportsModifiers() public function supportsModifiers()
{ {
// explain the export manager which formatters and filters are allowed // explain the export manager which formatters and filters are allowed
return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN); return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN);
} }
} }

View File

@@ -28,7 +28,7 @@ Then, render the pagination using the dedicated twig function.
.. code-block:: html+twig .. code-block:: html+twig
{% extends "@ChillPerson/Person/layout.html.twig" %} {% extends "ChillPersonBundle::layout.html.twig" %}
{% block title 'Item list'|trans %} {% block title 'Item list'|trans %}

View File

@@ -8,21 +8,21 @@ use Symfony\Component\HttpFoundation\Request;
class ItemController extends Controller { class ItemController extends Controller {
public function yourAction() public function yourAction()
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
// first, get the number of total item are available // first, get the number of total item are available
$total = $em $total = $em
->createQuery("SELECT COUNT (item.id) FROM ChillMyBundle:Item item") ->createQuery("SELECT COUNT (item.id) FROM ChillMyBundle:Item item")
->getSingleScalarResult(); ->getSingleScalarResult();
// get the PaginatorFactory // get the PaginatorFactory
$paginatorFactory = $this->get('chill_main.paginator_factory'); $paginatorFactory = $this->get('chill_main.paginator_factory');
// create a pagination instance. This instance is only valid for // create a pagination instance. This instance is only valid for
// the current route and parameters // the current route and parameters
$paginator = $paginatorFactory->create($total); $paginator = $paginatorFactory->create($total);
// launch your query on item. Limit the query to the results // launch your query on item. Limit the query to the results
// for the current page using the paginator // for the current page using the paginator
$items = $em->createQuery("SELECT item FROM ChillMyBundle:Item item WHERE <your clause>") $items = $em->createQuery("SELECT item FROM ChillMyBundle:Item item WHERE <your clause>")
@@ -30,12 +30,12 @@ class ItemController extends Controller {
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber()) ->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
// use the paginator to get the number of items to display // use the paginator to get the number of items to display
->setMaxResults($paginator->getItemsPerPage()); ->setMaxResults($paginator->getItemsPerPage());
return $this->render('ChillMyBundle:Item:list.html.twig', array( return $this->render('ChillMyBundle:Item:list.html.twig', array(
'items' => $items, 'items' => $items,
'paginator' => $paginator 'paginator' => $paginator
); )
);
} }
} }

View File

@@ -149,7 +149,7 @@ It proposes a new block :
* where to display the admin content * where to display the admin content
@ChillPersonBundle/Person/layout.html.twig ChillPersonBundle::layout.html.twig
----------------------------------- -----------------------------------
This layout extend `ChillMainBundle::layoutWithVerticalMenu.html.twig` add the person details in the block `top_banner`, set the menu `person` as the vertical menu. This layout extend `ChillMainBundle::layoutWithVerticalMenu.html.twig` add the person details in the block `top_banner`, set the menu `person` as the vertical menu.

22
grumphp.yml Normal file
View File

@@ -0,0 +1,22 @@
imports:
- { resource: tests/app/vendor/drupol/php-conventions/config/php73/grumphp.yml }
parameters:
tasks.license.name: AGPL-3.0
tasks.license.holder: Champs-Libres
tasks.phpstan.configuration: phpstan.neon
tasks.phpstan.ignore_patterns:
- /src\/Bundle\/(.*)\/migrations/
- /src\/Bundle\/(.*)\/Resources/
- /src\/Bundle\/(.*)\/Tests/
- /src\/Bundle\/(.*)\/Test/
- /src\/Bundle\/(.*)\/config/
- /src\/Bundle\/(.*)\/translations/
- /src\/Bundle\/(.*)\/DataFixtures/
- /^docs/
- /^tests/
skip_tasks:
- composer_require_checker
- phpcsfixer
- phpcs
- twigcs

View File

@@ -1,3 +0,0 @@
add npm/yarn dependency in package.json :
"select2-bootstrap-theme": "0.1.0-beta.10",

23979
phpstan-baseline.neon Normal file

File diff suppressed because it is too large Load Diff

3
phpstan.neon Normal file
View File

@@ -0,0 +1,3 @@
includes:
- phpstan-baseline.neon

View File

@@ -10,7 +10,7 @@
<php> <php>
<ini name="error_reporting" value="-1" /> <ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" /> <server name="APP_ENV" value="test" force="true" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" /> <env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
<server name="SHELL_VERBOSITY" value="-1" /> <server name="SHELL_VERBOSITY" value="-1" />
</php> </php>
@@ -31,12 +31,6 @@
<!-- temporarily removed, the time to find a fix --> <!-- temporarily removed, the time to find a fix -->
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude> <exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
</testsuite> </testsuite>
<testsuite name="AsideActivityBundle">
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
</testsuite>
<testsuite name="CalendarBundle">
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
</testsuite>
</testsuites> </testsuites>
<listeners> <listeners>

2022
psalm-baseline.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,16 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<psalm <psalm
errorLevel="3" errorLevel="7"
resolveFromConfigFile="true" resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config" xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
> >
<projectFiles> <projectFiles>
<directory name="src" /> <directory name="src" />
<ignoreFiles> <ignoreFiles>
<directory name="vendor" /> <directory name="tests/" />
</ignoreFiles> </ignoreFiles>
</projectFiles> </projectFiles>
</psalm> </psalm>

View File

@@ -22,25 +22,17 @@
namespace Chill\ActivityBundle\Controller; namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Privacy\PrivacyEvent; use Chill\PersonBundle\Privacy\PrivacyEvent;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\Person;
use Chill\ActivityBundle\Form\ActivityType; use Chill\ActivityBundle\Form\ActivityType;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Symfony\Component\Serializer\SerializerInterface;
/** /**
* Class ActivityController * Class ActivityController
@@ -49,288 +41,216 @@ use Symfony\Component\Serializer\SerializerInterface;
*/ */
class ActivityController extends AbstractController class ActivityController extends AbstractController
{ {
protected EventDispatcherInterface $eventDispatcher;
protected AuthorizationHelper $authorizationHelper; /**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
protected LoggerInterface $logger; /**
* @var AuthorizationHelper
*/
protected $authorizationHelper;
protected SerializerInterface $serializer; /**
* @var LoggerInterface
protected ActivityACLAwareRepositoryInterface $activityACLAwareRepository; */
protected $logger;
/**
* ActivityController constructor.
*
* @param EventDispatcherInterface $eventDispatcher
* @param AuthorizationHelper $authorizationHelper
*/
public function __construct( public function __construct(
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
EventDispatcherInterface $eventDispatcher, EventDispatcherInterface $eventDispatcher,
AuthorizationHelper $authorizationHelper, AuthorizationHelper $authorizationHelper,
LoggerInterface $logger, LoggerInterface $logger
SerializerInterface $serializer
) { ) {
$this->activityACLAwareRepository = $activityACLAwareRepository;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->logger = $logger; $this->logger = $logger;
$this->serializer = $serializer;
} }
/** /**
* Lists all Activity entities. * Lists all Activity entities.
*
*/ */
public function listAction(Request $request): Response public function listAction($person_id, Request $request)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$view = null; $person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
// TODO: add pagination
[$person, $accompanyingPeriod] = $this->getEntity($request); if ($person === NULL) {
throw $this->createNotFoundException('Person not found');
if ($person instanceof Person) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
$activities = $this->activityACLAwareRepository
->findByPerson($person, ActivityVoter::SEE, 0, null);
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'action' => 'list'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
$view = 'ChillActivityBundle:Activity:listPerson.html.twig';
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
$activities = $this->activityACLAwareRepository
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE);
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
} }
return $this->render($view, array( $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$reachableScopes = $this->authorizationHelper
->getReachableScopes($this->getUser(), new Role('CHILL_ACTIVITY_SEE'),
$person->getCenter());
$activities = $em->getRepository('ChillActivityBundle:Activity')
->findBy(
array('person' => $person, 'scope' => $reachableScopes),
array('date' => 'DESC')
);
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'action' => 'list'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillActivityBundle:Activity:list.html.twig', array(
'activities' => $activities, 'activities' => $activities,
'person' => $person, 'person' => $person
'accompanyingCourse' => $accompanyingPeriod,
)); ));
} }
/**
public function selectTypeAction(Request $request): Response * Creates a new Activity entity.
*
*/
public function createAction($person_id, Request $request)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$view = null; $person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
[$person, $accompanyingPeriod] = $this->getEntity($request); if ($person === NULL) {
throw $this->createNotFoundException('person not found');
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:selectTypeAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:selectTypePerson.html.twig';
} }
$data = []; $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$activityTypeCategories = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityTypeCategory::class)
->findBy(['active' => true], ['ordering' => 'ASC']);
foreach ($activityTypeCategories as $activityTypeCategory) {
$activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']);
$data[] = [
'activityTypeCategory' => $activityTypeCategory,
'activityTypes' => $activityTypes,
];
}
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
} else {
$activityData = [];
}
if ($view === null) {
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'data' => $data,
'activityData' => $activityData
]);
}
public function newAction(Request $request): Response
{
$em = $this->getDoctrine()->getManager();
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
}
$activityType_id = $request->get('activityType_id', 0);
$activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
->find($activityType_id);
$activityData = null;
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
}
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType ||
!$activityType->isActive()) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
$params['activityData'] = $activityData;
}
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
}
$entity = new Activity(); $entity = new Activity();
$entity->setUser($this->getUser()); $entity->setPerson($person);
$form = $this->createCreateForm($entity, $person);
$form->handleRequest($request);
if ($person instanceof Person) { if ($form->isValid()) {
$entity->setPerson($person); $em = $this->getDoctrine()->getManager();
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) { $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity,
$entity->setAccompanyingPeriod($accompanyingPeriod); 'creation of this activity not allowed');
}
$entity->setType($activityType);
$entity->setDate(new \DateTime('now'));
if ($request->query->has('activityData')) {
$activityData = $request->query->get('activityData');
if (array_key_exists('durationTime', $activityData)) {
$durationTimeInMinutes = $activityData['durationTime'];
$hours = floor($durationTimeInMinutes / 60);
$minutes = $durationTimeInMinutes % 60;
$duration = \DateTime::createFromFormat("H:i", $hours.':'.$minutes);
if ($duration) {
$entity->setDurationTime($duration);
}
}
if (array_key_exists('date', $activityData)) {
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
if ($date) {
$entity->setDate($date);
}
}
if (array_key_exists('personsId', $activityData)) {
foreach($activityData['personsId'] as $personId){
$concernedPerson = $em->getRepository(\Chill\PersonBundle\Entity\Person::class)->find($personId);
$entity->addPerson($concernedPerson);
}
}
if (array_key_exists('professionalsId', $activityData)) {
foreach($activityData['professionalsId'] as $professionalsId){
$professional = $em->getRepository(\Chill\ThirdPartyBundle\Entity\ThirdParty::class)->find($professionalsId);
$entity->addThirdParty($professional);
}
}
if (array_key_exists('comment', $activityData)) {
$comment = new CommentEmbeddable();
$comment->setComment($activityData['comment']);
$comment->setUserId($this->getUser()->getid());
$comment->setDate(new \DateTime('now'));
$entity->setComment($comment);
}
}
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($entity); $em->persist($entity);
$em->flush(); $em->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); $this->get('session')
->getFlashBag()
->add('success',
$this->get('translator')
->trans('Success : activity created!')
);
$params = $this->buildParamsToUrl($person, $accompanyingPeriod); return $this->redirect(
$this->generateUrl('chill_activity_activity_show',
$params['id'] = $entity->getId(); array('id' => $entity->getId(), 'person_id' => $person_id)));
return $this->redirectToRoute('chill_activity_activity_show', $params);
} }
if ($view === null) { $this->get('session')
throw $this->createNotFoundException('Template not found'); ->getFlashBag()->add('danger',
} $this->get('translator')
->trans('The form is not valid. The activity has not been created !')
);
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); return $this->render('ChillActivityBundle:Activity:new.html.twig', array(
return $this->render($view, [
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity, 'entity' => $entity,
'form' => $form->createView(), 'form' => $form->createView(),
'activity_json' => $activity_array 'person' => $person
]); ));
} }
public function showAction(Request $request, $id): Response /**
* Creates a form to create a Activity entity.
*
* @param Activity $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Activity $entity)
{
$form = $this->createForm(ActivityType::class, $entity,
array(
'action' => $this->generateUrl('chill_activity_activity_create', [
'person_id' => $entity->getPerson()->getId(),
]),
'method' => 'POST',
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_CREATE')
)
);
return $form;
}
/**
* Displays a form to create a new Activity entity.
*
*/
public function newAction($person_id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
[$person, $accompanyingPeriod] = $this->getEntity($request); if ($person === NULL){
throw $this->createNotFoundException('Person not found');
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
} }
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$entity = new Activity();
$entity->setUser($this->get('security.token_storage')->getToken()->getUser());
$entity->setPerson($person);
$entity->setDate(new \DateTime('now'));
$this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity);
$form = $this->createCreateForm($entity, $person);
return $this->render('ChillActivityBundle:Activity:new.html.twig', array(
'person' => $person,
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a Activity entity.
*
*/
public function showAction($person_id, $id)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
if (!$person) {
throw $this->createNotFoundException('person not found');
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$entity = $em->getRepository('ChillActivityBundle:Activity')->find($id); $entity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
if (!$entity) { if (!$entity) {
throw $this->createNotFoundException('Unable to find Activity entity.'); throw $this->createNotFoundException('Unable to find Activity entity.');
} }
if (null !== $accompanyingPeriod) { $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
$entity->personsAssociated = $entity->getPersonsAssociated();
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
}
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période $deleteForm = $this->createDeleteForm($id, $person);
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
$deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod);
// TODO
/*
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'element_id' => $entity->getId(), 'element_id' => $entity->getId(),
'action' => 'show' 'action' => 'show'
)); ));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if ($view === null) { return $this->render('ChillActivityBundle:Activity:show.html.twig', array(
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, array(
'person' => $person, 'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'entity' => $entity, 'entity' => $entity,
'delete_form' => $deleteForm->createView(), 'delete_form' => $deleteForm->createView(),
)); ));
@@ -340,70 +260,118 @@ class ActivityController extends AbstractController
* Displays a form to edit an existing Activity entity. * Displays a form to edit an existing Activity entity.
* *
*/ */
public function editAction($id, Request $request): Response public function editAction($person_id, $id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
[$person, $accompanyingPeriod] = $this->getEntity($request); if (!$person) {
throw $this->createNotFoundException('person not found');
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
} }
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$entity = $em->getRepository('ChillActivityBundle:Activity')->find($id); $entity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
if (!$entity) { if (!$entity) {
throw $this->createNotFoundException('Unable to find Activity entity.'); throw $this->createNotFoundException('Unable to find Activity entity.');
} }
// TODO $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
$form = $this->createForm(ActivityType::class, $entity, [ $editForm = $this->createEditForm($entity);
'center' => $entity->getCenter(), $deleteForm = $this->createDeleteForm($id, $person);
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($entity);
$em->flush();
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $id;
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
$deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod);
/*
* TODO
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'element_id' => $entity->getId(), 'element_id' => $entity->getId(),
'action' => 'edit' 'action' => 'edit'
)); ));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
*/
if ($view === null) { return $this->render('ChillActivityBundle:Activity:edit.html.twig', array(
throw $this->createNotFoundException('Template not found'); 'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
'person' => $person
));
}
/**
* Creates a form to edit a Activity entity.
*
* @param Activity $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Activity $entity)
{
$form = $this->createForm(ActivityType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activity_update',
array(
'id' => $entity->getId(),
'person_id' => $entity->getPerson()->getId()
)),
'method' => 'PUT',
'center' => $entity->getCenter(),
'role' => new Role('CHILL_ACTIVITY_UPDATE')
));
return $form;
}
/**
* Edits an existing Activity entity.
*
*/
public function updateAction(Request $request, $person_id, $id)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$entity = $em->getRepository('ChillActivityBundle:Activity')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
} }
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
return $this->render($view, array( $deleteForm = $this->createDeleteForm($id, $person);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
$event = new PrivacyEvent($person, array(
'element_class' => Activity::class,
'element_id' => $entity->getId(),
'action' => 'update'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
if ($editForm->isValid()) {
$em->flush();
$this->get('session')
->getFlashBag()
->add('success',
$this->get('translator')
->trans('Success : activity updated!')
);
return $this->redirect($this->generateUrl('chill_activity_activity_show', array('id' => $id, 'person_id' => $person_id)));
}
$this->get('session')
->getFlashBag()
->add('error',
$this->get('translator')
->trans('This form contains errors')
);
return $this->render('ChillActivityBundle:Activity:edit.html.twig', array(
'person' => $entity->getPerson(),
'entity' => $entity, 'entity' => $entity,
'edit_form' => $form->createView(), 'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(), 'delete_form' => $deleteForm->createView(),
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
'activity_json' => $activity_array
)); ));
} }
@@ -411,29 +379,22 @@ class ActivityController extends AbstractController
* Deletes a Activity entity. * Deletes a Activity entity.
* *
*/ */
public function deleteAction(Request $request, $id) public function deleteAction(Request $request, $id, $person_id)
{ {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
}
/* @var $activity Activity */ /* @var $activity Activity */
$activity = $em->getRepository('ChillActivityBundle:Activity')->find($id); $activity = $em->getRepository('ChillActivityBundle:Activity')
->find($id);
$person = $activity->getPerson();
if (!$activity) { if (!$activity) {
throw $this->createNotFoundException('Unable to find Activity entity.'); throw $this->createNotFoundException('Unable to find Activity entity.');
} }
// TODO $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity);
$form = $this->createDeleteForm($id, $person, $accompanyingPeriod); $form = $this->createDeleteForm($id, $person);
if ($request->getMethod() === Request::METHOD_DELETE) { if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request); $form->handleRequest($request);
@@ -443,14 +404,14 @@ class ActivityController extends AbstractController
$this->logger->notice("An activity has been removed", array( $this->logger->notice("An activity has been removed", array(
'by_user' => $this->getUser()->getUsername(), 'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(), 'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, 'person_id' => $activity->getPerson()->getId(),
'comment' => $activity->getComment()->getComment(), 'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, 'scope_id' => $activity->getScope()->getId(),
'reasons_ids' => $activity->getReasons() 'reasons_ids' => $activity->getReasons()
->map(function ($ar) { return $ar->getId(); }) ->map(function ($ar) { return $ar->getId(); })
->toArray(), ->toArray(),
'type_id' => $activity->getType()->getId(), 'type_id' => $activity->getType()->getId(),
'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, 'duration' => $activity->getDurationTime()->format('U'),
'date' => $activity->getDate()->format('Y-m-d'), 'date' => $activity->getDate()->format('Y-m-d'),
'attendee' => $activity->getAttendee() 'attendee' => $activity->getAttendee()
)); ));
@@ -461,86 +422,37 @@ class ActivityController extends AbstractController
$this->addFlash('success', $this->get('translator') $this->addFlash('success', $this->get('translator')
->trans("The activity has been successfully removed.")); ->trans("The activity has been successfully removed."));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod); return $this->redirect($this->generateUrl(
return $this->redirectToRoute('chill_activity_activity_list', $params); 'chill_activity_activity_list', array(
'person_id' => $person_id
)));
} }
} }
if ($view === null) { return $this->render('ChillActivityBundle:Activity:confirm_delete.html.twig', array(
throw $this->createNotFoundException('Template not found');
}
return $this->render($view, array(
'activity' => $activity, 'activity' => $activity,
'delete_form' => $form->createView(), 'delete_form' => $form->createView()
'person' => $person,
'accompanyingCourse' => $accompanyingPeriod,
)); ));
} }
/** /**
* Creates a form to delete a Activity entity by id. * Creates a form to delete a Activity entity by id.
*
* @param mixed $id The entity id
*
* @return \Symfony\Component\Form\Form The form
*/ */
private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form private function createDeleteForm($id, $person)
{ {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
$params['id'] = $id;
return $this->createFormBuilder() return $this->createFormBuilder()
->setAction($this->generateUrl('chill_activity_activity_delete', $params)) ->setAction($this->generateUrl(
'chill_activity_activity_delete',
array('id' => $id, 'person_id' => $person->getId())))
->setMethod('DELETE') ->setMethod('DELETE')
->add('submit', SubmitType::class, array('label' => 'Delete')) ->add('submit', SubmitType::class, array('label' => 'Delete'))
->getForm() ->getForm()
; ;
} }
private function getEntity(Request $request): array
{
$em = $this->getDoctrine()->getManager();
$person = $accompanyingPeriod = null;
if ($request->query->has('person_id')) {
$person_id = $request->get('person_id');
$person = $em->getRepository(Person::class)->find($person_id);
if ($person === null) {
throw $this->createNotFoundException('Person not found');
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
} elseif ($request->query->has('accompanying_period_id')) {
$accompanying_period_id = $request->get('accompanying_period_id');
$accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id);
if ($accompanyingPeriod === null) {
throw $this->createNotFoundException('Accompanying Period not found');
}
// TODO Add permission
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
} else {
throw $this->createNotFoundException("Person or Accompanying Period not found");
}
return [
$person, $accompanyingPeriod
];
}
private function buildParamsToUrl(
?Person $person,
?AccompanyingPeriod $accompanyingPeriod
): array {
$params = [];
if ($person) {
$params['person_id'] = $person->getId();
}
if ($accompanyingPeriod) {
$params['accompanying_period_id'] = $accompanyingPeriod->getId();
}
return $params;
}
} }

View File

@@ -0,0 +1,178 @@
<?php
namespace Chill\ActivityBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Form\ActivityTypeType;
/**
* Class ActivityTypeController
*
* @package Chill\ActivityBundle\Controller
*/
class ActivityTypeController extends AbstractController
{
/**
* Lists all ActivityType entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ChillActivityBundle:ActivityType')->findAll();
return $this->render('ChillActivityBundle:ActivityType:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new ActivityType entity.
*
*/
public function createAction(Request $request)
{
$entity = new ActivityType();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activitytype_show', array('id' => $entity->getId())));
}
return $this->render('ChillActivityBundle:ActivityType:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Creates a form to create a ActivityType entity.
*
* @param ActivityType $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(ActivityType $entity)
{
$form = $this->createForm(ActivityTypeType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activitytype_create'),
'method' => 'POST',
));
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new ActivityType entity.
*
*/
public function newAction()
{
$entity = new ActivityType();
$form = $this->createCreateForm($entity);
return $this->render('ChillActivityBundle:ActivityType:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a ActivityType entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityType')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityType entity.');
}
return $this->render('ChillActivityBundle:ActivityType:show.html.twig', array(
'entity' => $entity,
));
}
/**
* Displays a form to edit an existing ActivityType entity.
*
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityType')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityType entity.');
}
$editForm = $this->createEditForm($entity);
return $this->render('ChillActivityBundle:ActivityType:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView()
));
}
/**
* Creates a form to edit a ActivityType entity.
*
* @param ActivityType $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(ActivityType $entity)
{
$form = $this->createForm(ActivityTypeType::class, $entity, array(
'action' => $this->generateUrl('chill_activity_activitytype_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', SubmitType::class, array('label' => 'Update'));
return $form;
}
/**
* Edits an existing ActivityType entity.
*
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ChillActivityBundle:ActivityType')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityType entity.');
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('chill_activity_activitytype_edit', array('id' => $id)));
}
return $this->render('ChillActivityBundle:ActivityType:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
));
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
class AdminActivityPresenceController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.id', 'ASC');
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeCategoryController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.ordering', 'ASC');
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace Chill\ActivityBundle\Controller;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
class AdminActivityTypeController extends CRUDController
{
/**
* @param string $action
* @param \Doctrine\ORM\QueryBuilder|mixed $query
* @param Request $request
* @param PaginatorInterface $paginator
* @return \Doctrine\ORM\QueryBuilder|mixed
*/
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var \Doctrine\ORM\QueryBuilder $query */
return $query->orderBy('e.ordering', 'ASC');
}
}

View File

@@ -116,10 +116,9 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
->setDurationTime($this->faker->dateTime(36000)) ->setDurationTime($this->faker->dateTime(36000))
->setType($this->getRandomActivityType()) ->setType($this->getRandomActivityType())
->setScope($this->getRandomScope()) ->setScope($this->getRandomScope())
->setAttendee($this->faker->boolean())
; ;
// ->setAttendee($this->faker->boolean())
$usedId = array(); $usedId = array();
for ($i = 0; $i < rand(0, 4); $i++) { for ($i = 0; $i < rand(0, 4); $i++) {
$reason = $this->getRandomActivityReason($usedId); $reason = $this->getRandomActivityReason($usedId);
@@ -138,15 +137,11 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
foreach($persons as $person) { foreach($persons as $person) {
$activityNbr = rand(0,3); $activityNbr = rand(0,3);
$ref = 'activity_'.$person->getFullnameCanonical();
for($i = 0; $i < $activityNbr; $i ++) { for($i = 0; $i < $activityNbr; $i ++) {
print "Creating an activity type for : ".$person." (ref: ".$ref.") \n"; print "Creating an activity type for : ".$person."\n";
$activity = $this->newRandomActivity($person); $activity = $this->newRandomActivity($person);
$manager->persist($activity); $manager->persist($activity);
} }
$this->setReference($ref, $activity);
} }
$manager->flush(); $manager->flush();
} }

View File

@@ -1,39 +0,0 @@
<?php
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait;
use Chill\ActivityBundle\DataFixtures\ORM\LoadActivity;
/**
* Load notififications into database
*/
class LoadActivityNotifications extends AbstractFixture implements DependentFixtureInterface
{
use LoadAbstractNotificationsTrait;
public $notifs = [
[
'message' => 'Hello !',
'entityClass' => Activity::class,
'entityRef' => 'activity_gerard depardieu',
'sender' => 'center a_social',
'addressees' => [
'center a_social',
'center a_administrative',
'center a_direction',
'multi_center'
],
]
];
public function getDependencies()
{
return [
LoadActivity::class,
];
}
}

View File

@@ -2,27 +2,27 @@
/* /*
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the * published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\DataFixtures\ORM; namespace Chill\ActivityBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityType; use Chill\ActivityBundle\Entity\ActivityType;
@@ -32,59 +32,36 @@ use Chill\ActivityBundle\Entity\ActivityType;
* *
* @author Champs-Libres Coop * @author Champs-Libres Coop
*/ */
class LoadActivityType extends Fixture implements OrderedFixtureInterface class LoadActivityType extends AbstractFixture implements OrderedFixtureInterface
{ {
public function getOrder() public function getOrder()
{ {
return 16100; return 16100;
} }
public static $references = array(); public static $references = array();
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
$types = [ $types = [
# Exange [ 'name' =>
[ ['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel']],
'name' => [ 'name' =>
['fr' => 'Entretien physique avec l\'usager'], ['fr' => 'Entretien', 'en' => 'Interview', 'nl' => 'Vraaggesprek']],
'category' => 'exchange' ], [ 'name' =>
[ ['fr' => 'Inspection', 'en' => 'Inspection', 'nl' => 'Inspectie']]
'name' =>
['fr' => 'Appel téléphonique', 'en' => 'Telephone call', 'nl' => 'Telefoon appel'],
'category' => 'exchange' ],
[
'name' =>
['fr' => 'Courriel', 'en' => 'Email', 'nl' => 'Email'],
'category' => 'exchange' ],
# Meeting
[
'name' =>
['fr' => 'Point technique encadrant'],
'category' => 'meeting' ],
[
'name' =>
['fr' => 'Réunion avec des partenaires'],
'category' => 'meeting' ],
[
'name' =>
['fr' => 'Commission pluridisciplinaire et pluri-institutionnelle'],
'category' => 'meeting' ],
]; ];
foreach ($types as $t) { foreach ($types as $t) {
print "Creating activity type : " . $t['name']['fr'] . " (cat:". $t['category'] . " \n"; print "Creating activity type : " . $t['name']['en'] . "\n";
$activityType = (new ActivityType()) $activityType = (new ActivityType())
->setName(($t['name'])) ->setName(($t['name']));
->setCategory($this->getReference('activity_type_cat_'.$t['category']))
->setSocialIssuesVisible(1)
->setSocialActionsVisible(1);
$manager->persist($activityType); $manager->persist($activityType);
$reference = 'activity_type_'.$t['name']['fr']; $reference = 'activity_type_'.$t['name']['en'];
$this->addReference($reference, $activityType); $this->addReference($reference, $activityType);
static::$references[] = $reference; static::$references[] = $reference;
} }
$manager->flush(); $manager->flush();
} }
} }

View File

@@ -1,72 +0,0 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2014-2021, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\ActivityBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
/**
* Fixtures for ActivityTypeCategory
*
* @author Champs-Libres Coop
*/
class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterface
{
public static $references = array();
public function getOrder()
{
return 16050;
}
public function load(ObjectManager $manager)
{
$categories = [
[
'name' => ['fr' => 'Échange avec usager', 'en' => 'Exchange with user'],
'ref' => 'exchange',
],
[
'name' => ['fr' => 'Réunion', 'en' => 'Meeting'],
'ref' => 'meeting',
],
];
foreach ($categories as $cat) {
print "Creating activity type category : " . $cat['ref'] . "\n";
$newCat = (new ActivityTypeCategory())
->setName(($cat['name']));
$manager->persist($newCat);
$reference = 'activity_type_cat_'.$cat['ref'];
$this->addReference($reference, $newCat);
static::$references[] = $reference;
}
$manager->flush();
}
}

View File

@@ -3,7 +3,7 @@
/* /*
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@@ -44,7 +44,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
{ {
$configuration = new Configuration(); $configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs); $config = $this->processConfiguration($configuration, $configs);
$container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']); $container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
@@ -55,20 +55,18 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$loader->load('services/controller.yaml'); $loader->load('services/controller.yaml');
$loader->load('services/form.yaml'); $loader->load('services/form.yaml');
$loader->load('services/templating.yaml'); $loader->load('services/templating.yaml');
$loader->load('services/accompanyingPeriodConsistency.yaml');
} }
public function prepend(ContainerBuilder $container) public function prepend(ContainerBuilder $container)
{ {
$this->prependRoutes($container); $this->prependRoutes($container);
$this->prependAuthorization($container); $this->prependAuthorization($container);
$this->prependCruds($container);
} }
/* (non-PHPdoc) /* (non-PHPdoc)
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend() * @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
*/ */
public function prependRoutes(ContainerBuilder $container) public function prependRoutes(ContainerBuilder $container)
{ {
//add routes for custom bundle //add routes for custom bundle
$container->prependExtensionConfig('chill_main', array( $container->prependExtensionConfig('chill_main', array(
@@ -79,7 +77,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
) )
)); ));
} }
public function prependAuthorization(ContainerBuilder $container) public function prependAuthorization(ContainerBuilder $container)
{ {
$container->prependExtensionConfig('security', array( $container->prependExtensionConfig('security', array(
@@ -91,75 +89,4 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
) )
)); ));
} }
protected function prependCruds(ContainerBuilder $container)
{
$container->prependExtensionConfig('chill_main', [
'cruds' => [
[
'class' => \Chill\ActivityBundle\Entity\ActivityType::class,
'name' => 'activity_type',
'base_path' => '/admin/activity/type',
'form_class' => \Chill\ActivityBundle\Form\ActivityTypeType::class,
'controller' => \Chill\ActivityBundle\Controller\AdminActivityTypeController::class,
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityType/index.html.twig',
'role' => 'ROLE_ADMIN'
],
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/new.html.twig',
],
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityType/edit.html.twig',
]
]
],
[
'class' => \Chill\ActivityBundle\Entity\ActivityTypeCategory::class,
'name' => 'activity_type_category',
'base_path' => '/admin/activity/type_category',
'form_class' => \Chill\ActivityBundle\Form\ActivityTypeCategoryType::class,
'controller' => \Chill\ActivityBundle\Controller\AdminActivityTypeCategoryController::class,
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityTypeCategory/index.html.twig',
'role' => 'ROLE_ADMIN'
],
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/new.html.twig',
],
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityTypeCategory/edit.html.twig',
]
]
],
[
'class' => \Chill\ActivityBundle\Entity\ActivityPresence::class,
'name' => 'activity_presence',
'base_path' => '/admin/activity/presence',
'form_class' => \Chill\ActivityBundle\Form\ActivityPresenceType::class,
'controller' => \Chill\ActivityBundle\Controller\AdminActivityPresenceController::class,
'actions' => [
'index' => [
'template' => '@ChillActivity/ActivityPresence/index.html.twig',
'role' => 'ROLE_ADMIN'
],
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/new.html.twig',
],
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillActivity/ActivityPresence/edit.html.twig',
]
]
],
]
]);
}
} }

View File

@@ -20,26 +20,19 @@
namespace Chill\ActivityBundle\Entity; namespace Chill\ActivityBundle\Entity;
use Chill\DocStoreBundle\Entity\Document;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Center;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Entity\HasCenterInterface; use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasScopeInterface; use Chill\MainBundle\Entity\HasScopeInterface;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Chill\MainBundle\Validator\Constraints\Entity\UserCircleConsistency; use Chill\MainBundle\Validator\Constraints\Entity\UserCircleConsistency;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/** /**
* Class Activity * Class Activity
@@ -48,511 +41,311 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
* @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository") * @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
* @ORM\Table(name="activity") * @ORM\Table(name="activity")
* @ORM\HasLifecycleCallbacks() * @ORM\HasLifecycleCallbacks()
* @DiscriminatorMap(typeProperty="type", mapping={
* "activity"=Activity::class
* })
*/
/*
* TODO : revoir
* @UserCircleConsistency( * @UserCircleConsistency(
* "CHILL_ACTIVITY_SEE_DETAILS", * "CHILL_ACTIVITY_SEE_DETAILS",
* getUserFunction="getUser", * getUserFunction="getUser",
* path="scope") * path="scope")
*/ */
class Activity implements HasCenterInterface, HasScopeInterface
class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
{ {
const SENTRECEIVED_SENT = 'sent';
const SENTRECEIVED_RECEIVED = 'received';
/** /**
* @var integer
*
* @ORM\Id * @ORM\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"read"})
*/ */
private ?int $id = null; private $id;
/** /**
* @var User
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*/ */
private User $user; private $user;
/** /**
* @var \DateTime
* @ORM\Column(type="datetime") * @ORM\Column(type="datetime")
*/ */
private \DateTime $date; private $date;
/** /**
* @ORM\Column(type="time", nullable=true) * @var \DateTime
* @ORM\Column(type="time")
*/ */
private ?\DateTime $durationTime = null; private $durationTime;
/** /**
* @ORM\Column(type="time", nullable=true) * @var boolean
* @ORM\Column(type="boolean")
*/ */
private ?\DateTime $travelTime = null; private $attendee;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
*/
private ?ActivityPresence $attendee = null;
/** /**
* @var ActivityReason
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason") * @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
*/ */
private Collection $reasons; private $reasons;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
* @Groups({"read"})
*/
private Collection $socialIssues;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
* @Groups({"read"})
*/
private Collection $socialActions;
/** /**
* @var ActivityType
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType") * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
*/ */
private ActivityType $type; private $type;
/** /**
* @var Scope
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope") * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*/ */
private ?Scope $scope = null; private $scope;
/** /**
* @var Person
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person") * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/ */
private ?Person $person = null; private $person;
/**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
* @Groups({"read"})
*/
private ?AccompanyingPeriod $accompanyingPeriod = null;
/** /**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_") * @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
*/ */
private CommentEmbeddable $comment; private $comment;
/** /**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person") * Activity constructor.
* @Groups({"read"})
*/ */
private ?Collection $persons = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
* @Groups({"read"})
*/
private ?Collection $thirdParties = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject")
*/
private Collection $documents;
/**
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
* @Groups({"read"})
*/
private ?Collection $users = null;
/**
* @ORM\Column(type="boolean", options={"default"=false})
*/
private bool $emergency = false;
/**
* @ORM\Column(type="string", options={"default"=""})
*/
private string $sentReceived = '';
public function __construct() public function __construct()
{ {
$this->reasons = new ArrayCollection(); $this->reasons = new ArrayCollection();
$this->comment = new CommentEmbeddable(); $this->comment = new CommentEmbeddable();
$this->persons = new ArrayCollection();
$this->thirdParties = new ArrayCollection();
$this->documents = new ArrayCollection();
$this->users = new ArrayCollection();
$this->socialIssues = new ArrayCollection();
$this->socialActions = new ArrayCollection();
} }
public function getId(): ?int /**
* Get id
*
* @return integer
*/
public function getId()
{ {
return $this->id; return $this->id;
} }
public function setUser(User $user): self /**
* Set user
*
* @param User $user
* @return Activity
*/
public function setUser(User $user)
{ {
$this->user = $user; $this->user = $user;
return $this; return $this;
} }
public function getUser(): User /**
* Get user
*
* @return User
*/
public function getUser()
{ {
return $this->user; return $this->user;
} }
public function setDate(\DateTime $date): self /**
* Set date
*
* @param \DateTime $date
* @return Activity
*/
public function setDate($date)
{ {
$this->date = $date; $this->date = $date;
return $this; return $this;
} }
public function getDate(): \DateTime /**
* Get date
*
* @return \DateTime
*/
public function getDate()
{ {
return $this->date; return $this->date;
} }
public function setDurationTime(?\DateTime $durationTime): self /**
* Set durationTime
*
* @param \DateTime $durationTime
* @return Activity
*/
public function setDurationTime($durationTime)
{ {
$this->durationTime = $durationTime; $this->durationTime = $durationTime;
return $this; return $this;
} }
public function getDurationTime(): ?\DateTime /**
* Get durationTime
*
* @return \DateTime
*/
public function getDurationTime()
{ {
return $this->durationTime; return $this->durationTime;
} }
public function setTravelTime(\DateTime $travelTime): self /**
{ * Set attendee
$this->travelTime = $travelTime; *
* @param boolean $attendee
return $this; * @return Activity
} */
public function setAttendee($attendee)
public function getTravelTime(): ?\DateTime
{
return $this->travelTime;
}
public function setAttendee(ActivityPresence $attendee): self
{ {
$this->attendee = $attendee; $this->attendee = $attendee;
return $this; return $this;
} }
public function getAttendee(): ?ActivityPresence /**
* Get attendee
*
* @return boolean
*/
public function getAttendee()
{ {
return $this->attendee; return $this->attendee;
} }
public function addReason(ActivityReason $reason): self /**
* Add a reason
*
* @param ActivityReason $reason
* @return Activity
*/
public function addReason(ActivityReason $reason)
{ {
$this->reasons->add($reason); $this->reasons[] = $reason;
return $this; return $this;
} }
public function removeReason(ActivityReason $reason): void /**
* @param ActivityReason $reason
*/
public function removeReason(ActivityReason $reason)
{ {
$this->reasons->removeElement($reason); $this->reasons->removeElement($reason);
} }
public function getReasons(): Collection /**
* Get reasons
*
* @return Collection
*/
public function getReasons()
{ {
return $this->reasons; return $this->reasons;
} }
public function setReasons(?ArrayCollection $reasons): self /**
{ * Set type
$this->reasons = $reasons; *
* @param ActivityType $type
return $this; * @return Activity
} */
public function setType(ActivityType $type)
public function getSocialIssues(): Collection
{
return $this->socialIssues;
}
public function addSocialIssue(SocialIssue $socialIssue): self
{
if (!$this->socialIssues->contains($socialIssue)) {
$this->socialIssues[] = $socialIssue;
}
return $this;
}
public function removeSocialIssue(SocialIssue $socialIssue): self
{
$this->socialIssues->removeElement($socialIssue);
return $this;
}
public function getSocialActions(): Collection
{
return $this->socialActions;
}
public function addSocialAction(SocialAction $socialAction): self
{
if (!$this->socialActions->contains($socialAction)) {
$this->socialActions[] = $socialAction;
}
return $this;
}
public function removeSocialAction(SocialAction $socialAction): self
{
$this->socialActions->removeElement($socialAction);
return $this;
}
public function setType(ActivityType $type): self
{ {
$this->type = $type; $this->type = $type;
return $this; return $this;
} }
public function getType(): ActivityType /**
* Get type
*
* @return ActivityType
*/
public function getType()
{ {
return $this->type; return $this->type;
} }
public function setScope(Scope $scope): self /**
* Set scope
*
* @param Scope $scope
* @return Activity
*/
public function setScope(Scope $scope)
{ {
$this->scope = $scope; $this->scope = $scope;
return $this; return $this;
} }
public function getScope(): ?Scope /**
* Get scope
*
* @return Scope
*/
public function getScope()
{ {
return $this->scope; return $this->scope;
} }
public function setPerson(?Person $person): self /**
* Set person
*
* @param Person $person
* @return Activity
*/
public function setPerson(Person $person)
{ {
$this->person = $person; $this->person = $person;
return $this; return $this;
} }
public function getPerson(): ?Person /**
* Get person
*
* @return Person
*/
public function getPerson()
{ {
return $this->person; return $this->person;
} }
public function getAccompanyingPeriod(): ?AccompanyingPeriod
{
return $this->accompanyingPeriod;
}
public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self
{
$this->accompanyingPeriod = $accompanyingPeriod;
return $this;
}
/** /**
* get the center * get the center
* center is extracted from person * center is extracted from person
*
* @return Center
*/ */
public function getCenter(): ?Center public function getCenter()
{ {
if ($this->person instanceof Person) { return $this->person->getCenter();
return $this->person->getCenter();
}
return null;
} }
public function getComment(): CommentEmbeddable /**
* @return \Chill\MainBundle\Entity\Embeddalbe\CommentEmbeddable
*/
public function getComment()
{ {
return $this->comment; return $this->comment;
} }
public function setComment(CommentEmbeddable $comment): self /**
* @param \Chill\MainBundle\Entity\Embeddalbe\CommentEmbeddable $comment
*/
public function setComment($comment)
{ {
$this->comment = $comment; $this->comment = $comment;
return $this;
}
/**
* Add a person to the person list
*/
public function addPerson(?Person $person): self
{
if (null !== $person) {
$this->persons[] = $person;
}
return $this;
}
public function removePerson(Person $person): void
{
$this->persons->removeElement($person);
}
public function getPersons(): Collection
{
return $this->persons;
}
public function getPersonsAssociated(): array
{
if (null !== $this->accompanyingPeriod) {
$personsAssociated = [];
foreach ($this->accompanyingPeriod->getParticipations() as $participation) {
if ($this->persons->contains($participation->getPerson())) {
$personsAssociated[] = $participation->getPerson();
}
}
return $personsAssociated;
}
return [];
}
public function getPersonsNotAssociated(): array
{
if (null !== $this->accompanyingPeriod) {
$personsNotAssociated = [];
foreach ($this->persons as $person) {
if (!in_array($person, $this->getPersonsAssociated())) {
$personsNotAssociated[] = $person;
}
}
return $personsNotAssociated;
}
return [];
}
public function setPersons(?Collection $persons): self
{
$this->persons = $persons;
return $this;
}
public function addThirdParty(?ThirdParty $thirdParty): self
{
if (null !== $thirdParty) {
$this->thirdParties[] = $thirdParty;
}
return $this;
}
public function removeThirdParty(ThirdParty $thirdParty): void
{
$this->thirdParties->removeElement($thirdParty);
}
public function getThirdParties(): Collection
{
return $this->thirdParties;
}
public function setThirdParties(?Collection $thirdParties): self
{
$this->thirdParties = $thirdParties;
return $this;
}
public function addDocument(Document $document): self
{
$this->documents[] = $document;
return $this;
}
public function removeDocument(Document $document): void
{
$this->documents->removeElement($document);
}
public function getDocuments(): Collection
{
return $this->documents;
}
public function setDocuments(Collection $documents): self
{
$this->documents = $documents;
return $this;
}
public function addUser(?User $user): self
{
if (null !== $user) {
$this->users[] = $user;
}
return $this;
}
public function removeUser(User $user): void
{
$this->users->removeElement($user);
}
public function getUsers(): Collection
{
return $this->users;
}
public function setUsers(?Collection $users): self
{
$this->users = $users;
return $this;
}
public function isEmergency(): bool
{
return $this->getEmergency();
}
public function getEmergency(): bool
{
return $this->emergency;
}
public function setEmergency(bool $emergency): self
{
$this->emergency = $emergency;
return $this;
}
public function getSentReceived(): string
{
return $this->sentReceived;
}
public function setSentReceived(?string $sentReceived): self
{
$this->sentReceived = (string) $sentReceived;
return $this;
} }
} }

View File

@@ -1,97 +0,0 @@
<?php
/*
*
* Copyright (C) 2015, 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\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class ActivityPresence
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Table(name="activitytpresence")
* @ORM\HasLifecycleCallbacks()
*/
class ActivityPresence
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id;
/**
* @ORM\Column(type="json")
*/
private array $name = [];
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
public function getId(): int
{
return $this->id;
}
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
public function getName(): array
{
return $this->name;
}
/**
* Get active
* return true if the category type is active.
*/
public function getActive(): bool
{
return $this->active;
}
/**
* Is active
* return true if the category type is active
*/
public function isActive(): bool
{
return $this->getActive();
}
/**
* Set active
* set to true if the category type is active
*/
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
}

View File

@@ -1,19 +1,19 @@
<?php <?php
/* /*
* *
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop> * Copyright (C) 2015, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the * published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -32,239 +32,45 @@ use Doctrine\ORM\Mapping as ORM;
*/ */
class ActivityType class ActivityType
{ {
const FIELD_INVISIBLE = 0;
const FIELD_OPTIONAL = 1;
const FIELD_REQUIRED = 2;
/** /**
* @var integer
*
* @ORM\Id * @ORM\Id
* @ORM\Column(name="id", type="integer") * @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO") * @ORM\GeneratedValue(strategy="AUTO")
*/ */
private ?int $id; private $id;
/** /**
* @var array
* @ORM\Column(type="json_array") * @ORM\Column(type="json_array")
*/ */
private array $name = []; private $name;
/** /**
* @var bool
* @ORM\Column(type="boolean") * @ORM\Column(type="boolean")
*/ */
private bool $active = true; private $active = true;
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityTypeCategory")
*/
private ?ActivityTypeCategory $category = null;
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=2})
*/
private int $personVisible = self::FIELD_REQUIRED;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $personLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=2})
*/
private int $userVisible = self::FIELD_REQUIRED;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $userLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=2})
*/
private int $dateVisible = self::FIELD_REQUIRED;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $dateLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $placeVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $placeLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $personsVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $personsLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $thirdPartiesVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $thirdPartiesLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $durationTimeVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $durationTimeLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $travelTimeVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $travelTimeLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $attendeeVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $attendeeLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $reasonsVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $reasonsLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $commentVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $commentLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $sentReceivedVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $sentReceivedLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $documentsVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $documentsLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $usersVisible = self::FIELD_OPTIONAL;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $usersLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $emergencyVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $emergencyLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $accompanyingPeriodLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $socialDataVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $socialDataLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $socialIssuesVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $socialIssuesLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default"=1})
*/
private int $socialActionsVisible = self::FIELD_INVISIBLE;
/**
* @ORM\Column(type="string", nullable=false, options={"default"=""})
*/
private string $socialActionsLabel = '';
/**
* @ORM\Column(type="float", options={"default"="0.0"})
*/
private float $ordering = 0.0;
/** /**
* Get id * Get id
*
* @return integer
*/ */
public function getId(): int public function getId()
{ {
return $this->id; return $this->id;
} }
/** /**
* Set name * Set name
*
* @param array $name
* @return ActivityType
*/ */
public function setName(array $name): self public function setName($name)
{ {
$this->name = $name; $this->name = $name;
@@ -273,551 +79,58 @@ class ActivityType
/** /**
* Get name * Get name
*
* @return array | string
*/ */
public function getName(): array public function getName($locale = null)
{ {
return $this->name; if ($locale) {
if (isset($this->name[$locale])) {
return $this->name[$locale];
} else {
foreach ($this->name as $name) {
if (!empty($name)) {
return $name;
}
}
}
return '';
} else {
return $this->name;
}
} }
/** /**
* Get active * Get active
* return true if the type is active. * return true if the type is active.
*
* @return boolean
*/ */
public function getActive(): bool public function getActive() {
{
return $this->active; return $this->active;
} }
/** /**
* Is active * Is active
* return true if the type is active * return true if the type is active
*
* @return boolean
*/ */
public function isActive(): bool public function isActive() {
{
return $this->getActive(); return $this->getActive();
} }
/** /**
* Set active * Set active
* set to true if the type is active * set to true if the type is active
*
* @param boolean $active
* @return ActivityType
*/ */
public function setActive(bool $active): self public function setActive($active) {
{
$this->active = $active; $this->active = $active;
return $this; return $this;
} }
public function getCategory(): ?ActivityTypeCategory
{
return $this->category;
}
public function setCategory(?ActivityTypeCategory $category): self
{
$this->category = $category;
return $this;
}
public function getPersonVisible(): int
{
return $this->personVisible;
}
public function setPersonVisible(int $personVisible): self
{
$this->personVisible = $personVisible;
return $this;
}
public function getPersonLabel(): string
{
return $this->personLabel;
}
public function setPersonLabel(string $personLabel): self
{
$this->personLabel = $personLabel;
return $this;
}
public function getUserVisible(): int
{
return $this->userVisible;
}
public function setUserVisible(int $userVisible): self
{
$this->userVisible = $userVisible;
return $this;
}
public function getUserLabel(): string
{
return $this->userLabel;
}
public function setUserLabel(string $userLabel): self
{
$this->userLabel = $userLabel;
return $this;
}
public function getDateVisible(): int
{
return $this->dateVisible;
}
public function setDateVisible(int $dateVisible): self
{
$this->dateVisible = $dateVisible;
return $this;
}
public function getDateLabel(): string
{
return $this->dateLabel;
}
public function setDateLabel(string $dateLabel): self
{
$this->dateLabel = $dateLabel;
return $this;
}
public function getPlaceVisible(): int
{
return $this->placeVisible;
}
public function setPlaceVisible(int $placeVisible): self
{
$this->placeVisible = $placeVisible;
return $this;
}
public function getPlaceLabel(): string
{
return $this->placeLabel;
}
public function setPlaceLabel(string $placeLabel): self
{
$this->placeLabel = $placeLabel;
return $this;
}
public function getPersonsVisible(): int
{
return $this->personsVisible;
}
public function setPersonsVisible(int $personsVisible): self
{
$this->personsVisible = $personsVisible;
return $this;
}
public function getPersonsLabel(): string
{
return $this->personsLabel;
}
public function setPersonsLabel(string $personsLabel): self
{
$this->personsLabel = $personsLabel;
return $this;
}
public function getThirdPartiesVisible(): int
{
return $this->thirdPartiesVisible;
}
public function setThirdPartiesVisible(int $thirdPartiesVisible): self
{
$this->thirdPartiesVisible = $thirdPartiesVisible;
return $this;
}
public function getThirdPartiesLabel(): string
{
return $this->thirdPartiesLabel;
}
public function setThirdPartiesLabel(string $thirdPartiesLabel): self
{
$this->thirdPartiesLabel = $thirdPartiesLabel;
return $this;
}
public function getDurationTimeVisible(): int
{
return $this->durationTimeVisible;
}
public function setDurationTimeVisible(int $durationTimeVisible): self
{
$this->durationTimeVisible = $durationTimeVisible;
return $this;
}
public function getDurationTimeLabel(): string
{
return $this->durationTimeLabel;
}
public function setDurationTimeLabel(string $durationTimeLabel): self
{
$this->durationTimeLabel = $durationTimeLabel;
return $this;
}
public function getTravelTimeVisible(): int
{
return $this->travelTimeVisible;
}
public function setTravelTimeVisible(int $TravelTimeVisible): self
{
$this->travelTimeVisible = $TravelTimeVisible;
return $this;
}
public function getTravelTimeLabel(): string
{
return $this->travelTimeLabel;
}
public function setTravelTimeLabel(string $TravelTimeLabel): self
{
$this->travelTimeLabel = $TravelTimeLabel;
return $this;
}
public function getAttendeeVisible(): int
{
return $this->attendeeVisible;
}
public function setAttendeeVisible(int $attendeeVisible): self
{
$this->attendeeVisible = $attendeeVisible;
return $this;
}
public function getAttendeeLabel(): string
{
return $this->attendeeLabel;
}
public function setAttendeeLabel(string $attendeeLabel): self
{
$this->attendeeLabel = $attendeeLabel;
return $this;
}
public function getReasonsVisible(): int
{
return $this->reasonsVisible;
}
public function setReasonsVisible(int $reasonsVisible): self
{
$this->reasonsVisible = $reasonsVisible;
return $this;
}
public function getReasonsLabel(): string
{
return $this->reasonsLabel;
}
public function setReasonsLabel(string $reasonsLabel): self
{
$this->reasonsLabel = $reasonsLabel;
return $this;
}
public function getCommentVisible(): int
{
return $this->commentVisible;
}
public function setCommentVisible(int $commentVisible): self
{
$this->commentVisible = $commentVisible;
return $this;
}
public function getCommentLabel(): string
{
return $this->commentLabel;
}
public function setCommentLabel(string $commentLabel): self
{
$this->commentLabel = $commentLabel;
return $this;
}
public function getSentReceivedVisible(): int
{
return $this->sentReceivedVisible;
}
public function setSentReceivedVisible(int $sentReceivedVisible): self
{
$this->sentReceivedVisible = $sentReceivedVisible;
return $this;
}
public function getSentReceivedLabel(): string
{
return $this->sentReceivedLabel;
}
public function setSentReceivedLabel(string $sentReceivedLabel): self
{
$this->sentReceivedLabel = $sentReceivedLabel;
return $this;
}
public function getDocumentsVisible(): int
{
return $this->documentsVisible;
}
public function setDocumentsVisible(int $documentsVisible): self
{
$this->documentsVisible = $documentsVisible;
return $this;
}
public function getDocumentsLabel(): string
{
return $this->documentsLabel;
}
public function setDocumentsLabel(string $documentsLabel): self
{
$this->documentsLabel = $documentsLabel;
return $this;
}
public function getUsersVisible(): int
{
return $this->usersVisible;
}
public function setUsersVisible(int $usersVisible): self
{
$this->usersVisible = $usersVisible;
return $this;
}
public function getUsersLabel(): string
{
return $this->usersLabel;
}
public function setUsersLabel(string $usersLabel): self
{
$this->usersLabel = $usersLabel;
return $this;
}
public function getEmergencyVisible(): int
{
return $this->emergencyVisible;
}
public function setEmergencyVisible(int $emergencyVisible): self
{
$this->emergencyVisible = $emergencyVisible;
return $this;
}
public function getEmergencyLabel(): string
{
return $this->emergencyLabel;
}
public function setEmergencyLabel(string $emergencyLabel): self
{
$this->emergencyLabel = $emergencyLabel;
return $this;
}
public function getAccompanyingPeriodVisible(): int
{
return $this->accompanyingPeriodVisible;
}
public function setAccompanyingPeriodVisible(int $accompanyingPeriodVisible): self
{
$this->accompanyingPeriodVisible = $accompanyingPeriodVisible;
return $this;
}
public function getAccompanyingPeriodLabel(): string
{
return $this->accompanyingPeriodLabel;
}
public function setAccompanyingPeriodLabel(string $accompanyingPeriodLabel): self
{
$this->accompanyingPeriodLabel = $accompanyingPeriodLabel;
return $this;
}
public function getSocialDataVisible(): int
{
return $this->socialDataVisible;
}
public function setSocialDataVisible(int $socialDataVisible): self
{
$this->socialDataVisible = $socialDataVisible;
return $this;
}
public function getSocialDataLabel(): string
{
return $this->socialDataLabel;
}
public function setSocialDataLabel(string $socialDataLabel): self
{
$this->socialDataLabel = $socialDataLabel;
return $this;
}
public function isVisible(string $field): bool
{
$property = $field.'Visible';
if (!property_exists($this, $property)) {
throw new \InvalidArgumentException('Field "'.$field.'" not found');
}
return self::FIELD_INVISIBLE !== $this->$property;
}
public function isRequired(string $field): bool
{
$property = $field.'Visible';
if (!property_exists($this, $property)) {
throw new \InvalidArgumentException('Field "'.$field.'" not found');
}
return self::FIELD_REQUIRED === $this->$property;
}
public function getLabel(string $field): ?string
{
$property = $field.'Label';
if (!property_exists($this, $property)) {
throw new \InvalidArgumentException('Field "'.$field.'" not found');
}
return $this->$property;
}
public function getOrdering(): float
{
return $this->ordering;
}
public function setOrdering(float $ordering): self
{
$this->ordering = $ordering;
return $this;
}
public function getSocialIssuesVisible(): ?int
{
return $this->socialIssuesVisible;
}
public function setSocialIssuesVisible(int $socialIssuesVisible): self
{
$this->socialIssuesVisible = $socialIssuesVisible;
return $this;
}
public function getSocialIssuesLabel(): ?string
{
return $this->socialIssuesLabel;
}
public function setSocialIssuesLabel(string $socialIssuesLabel): self
{
$this->socialIssuesLabel = $socialIssuesLabel;
return $this;
}
public function getSocialActionsVisible(): ?int
{
return $this->socialActionsVisible;
}
public function setSocialActionsVisible(int $socialActionsVisible): self
{
$this->socialActionsVisible = $socialActionsVisible;
return $this;
}
public function getSocialActionsLabel(): ?string
{
return $this->socialActionsLabel;
}
public function setSocialActionsLabel(string $socialActionsLabel): self
{
$this->socialActionsLabel = $socialActionsLabel;
return $this;
}
} }

View File

@@ -1,123 +0,0 @@
<?php
/*
*
* Copyright (C) 2015, 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\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class ActivityTypeCateogry
*
* @package Chill\ActivityBundle\Entity
* @ORM\Entity()
* @ORM\Table(name="activitytypecategory")
* @ORM\HasLifecycleCallbacks()
*/
class ActivityTypeCategory
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id;
/**
* @ORM\Column(type="json_array")
*/
private array $name = [];
/**
* @ORM\Column(type="boolean")
*/
private bool $active = true;
/**
* @ORM\Column(type="float", options={"default"="0.0"})
*/
private float $ordering = 0.0;
/**
* Get id
*/
public function getId(): int
{
return $this->id;
}
/**
* Set name
*/
public function setName(array $name): self
{
$this->name = $name;
return $this;
}
/**
* Get name
*/
public function getName(): array
{
return $this->name;
}
/**
* Get active
* return true if the category type is active.
*/
public function getActive(): bool
{
return $this->active;
}
/**
* Is active
* return true if the category type is active
*/
public function isActive(): bool
{
return $this->getActive();
}
/**
* Set active
* set to true if the category type is active
*/
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getOrdering(): float
{
return $this->ordering;
}
public function setOrdering(float $ordering): self
{
$this->ordering = $ordering;
return $this;
}
}

View File

@@ -1,33 +0,0 @@
<?php
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityPresenceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array(
'choices' => array(
'Yes' => true,
'No' => false
),
'expanded' => true
));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => ActivityPresence::class
));
}
}

View File

@@ -2,21 +2,8 @@
namespace Chill\ActivityBundle\Form; namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\CommentType; use Chill\MainBundle\Form\Type\CommentType;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
@@ -28,363 +15,178 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTra
use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\ActivityBundle\Form\Type\TranslatableActivityType;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReason;
use Chill\MainBundle\Form\Type\UserPickerType; use Chill\MainBundle\Form\Type\UserPickerType;
use Chill\MainBundle\Form\Type\ScopePickerType; use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillDateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\CallbackTransformer;
use Chill\PersonBundle\Form\DataTransformer\PersonToIdTransformer;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
class ActivityType extends AbstractType class ActivityType extends AbstractType
{ {
protected User $user;
protected AuthorizationHelper $authorizationHelper; /**
* the user running this form
*
* @var User
*/
protected $user;
protected ObjectManager $om; /**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
protected TranslatableStringHelper $translatableStringHelper; /**
*
* @var ObjectManager
*/
protected $om;
protected SocialIssueRender $socialIssueRender; /**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
protected SocialActionRender $socialActionRender; protected $timeChoices;
protected array $timeChoices; public function __construct(
TokenStorageInterface $tokenStorage,
public function __construct ( AuthorizationHelper $authorizationHelper, ObjectManager $om,
TokenStorageInterface $tokenStorage, TranslatableStringHelper $translatableStringHelper,
AuthorizationHelper $authorizationHelper, array $timeChoices
ObjectManager $om, )
TranslatableStringHelper $translatableStringHelper, {
array $timeChoices,
SocialIssueRender $socialIssueRender,
SocialActionRender $socialActionRender
) {
if (!$tokenStorage->getToken()->getUser() instanceof User) { if (!$tokenStorage->getToken()->getUser() instanceof User) {
throw new \RuntimeException("you should have a valid user"); throw new \RuntimeException("you should have a valid user");
} }
$this->user = $tokenStorage->getToken()->getUser(); $this->user = $tokenStorage->getToken()->getUser();
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->om = $om; $this->om = $om;
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
$this->timeChoices = $timeChoices; $this->timeChoices = $timeChoices;
$this->socialIssueRender = $socialIssueRender;
$this->socialActionRender = $socialActionRender;
} }
public function buildForm(FormBuilderInterface $builder, array $options): void /**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{ {
// handle times choices // handle times choices
$timeChoices = []; $timeChoices = array();
foreach ($this->timeChoices as $e) { foreach ($this->timeChoices as $e) {
$timeChoices[$e['label']] = $e['seconds']; $timeChoices[$e['label']] = $e['seconds'];
} };
$durationTimeTransformer = new DateTimeToTimestampTransformer('GMT', 'GMT'); $durationTimeTransformer = new DateTimeToTimestampTransformer('GMT', 'GMT');
$durationTimeOptions = [ $durationTimeOptions = array(
'choices' => $timeChoices, 'choices' => $timeChoices,
'placeholder' => 'Choose the duration', 'placeholder' => 'Choose the duration',
]; );
/** @var \Chill\ActivityBundle\Entity\ActivityType $activityType */ $builder
$activityType = $options['activityType']; ->add('date', ChillDateType::class, array(
'required' => true
if (!$activityType->isActive()) { ))
throw new \InvalidArgumentException('Activity type must be active'); ->add('durationTime', ChoiceType::class, $durationTimeOptions)
} ->add('attendee', ChoiceType::class, array(
'expanded' => true,
// TODO revoir la gestion des center au niveau du form des activité. 'required' => false,
if ($options['center']) { 'choices' => array(
$builder->add('scope', ScopePickerType::class, [ 'present' => true,
'center' => $options['center'], 'not present' => false
'role' => $options['role'] )
]); ))
} ->add('user', UserPickerType::class, [
/** @var ? \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingPeriod */
$accompanyingPeriod = NULL;
if ($options['accompanyingPeriod']) {
$accompanyingPeriod = $options['accompanyingPeriod'];
}
if ($activityType->isVisible('socialIssues') && $accompanyingPeriod) {
$builder->add('socialIssues', HiddenType::class);
$builder->get('socialIssues')
->addModelTransformer(new CallbackTransformer(
function (iterable $socialIssuesAsIterable): string {
$socialIssueIds = [];
foreach ($socialIssuesAsIterable as $value) {
$socialIssueIds[] = $value->getId();
}
return implode(',', $socialIssueIds);
},
function (?string $socialIssuesAsString): array {
if (null === $socialIssuesAsString) {
return [];
}
return array_map(
fn(string $id): ?SocialIssue => $this->om->getRepository(SocialIssue::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialIssuesAsString)
);
}
))
;
}
if ($activityType->isVisible('socialActions') && $accompanyingPeriod) {
$builder->add('socialActions', HiddenType::class);
$builder->get('socialActions')
->addModelTransformer(new CallbackTransformer(
function (iterable $socialActionsAsIterable): string {
$socialActionIds = [];
foreach ($socialActionsAsIterable as $value) {
$socialActionIds[] = $value->getId();
}
return implode(',', $socialActionIds);
},
function (?string $socialActionsAsString): array {
if (null === $socialActionsAsString) {
return [];
}
return array_map(
fn(string $id): ?SocialAction => $this->om->getRepository(SocialAction::class)->findOneBy(['id' => (int) $id]),
explode(',', $socialActionsAsString)
);
}
))
;
}
if ($activityType->isVisible('date')) {
$builder->add('date', ChillDateType::class, [
'label' => $activityType->getLabel('date'),
'required' => $activityType->isRequired('date'),
]);
}
if ($activityType->isVisible('durationTime')) {
$durationTimeOptions['label'] = $activityType->getLabel('durationTime');
$durationTimeOptions['required'] = $activityType->isRequired('durationTime');
$builder->add('durationTime', ChoiceType::class, $durationTimeOptions);
}
if ($activityType->isVisible('travelTime')) {
$durationTimeOptions['label'] = $activityType->getLabel('travelTime');
$durationTimeOptions['required'] = $activityType->isRequired('travelTime');
$builder->add('travelTime', ChoiceType::class, $durationTimeOptions);
}
if ($activityType->isVisible('attendee')) {
$builder->add('attendee', EntityType::class, [
'label' => $activityType->getLabel('attendee'),
'required' => $activityType->isRequired('attendee'),
'expanded' => true,
'class' => ActivityPresence::class,
'choice_label' => function (ActivityPresence $activityPresence) {
return $this->translatableStringHelper->localize($activityPresence->getName());
},
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('a')
->where('a.active = true');
},
]);
}
if ($activityType->isVisible('user') && $options['center']) {
$builder->add('user', UserPickerType::class, [
'label' => $activityType->getLabel('user'),
'required' => $activityType->isRequired('user'),
'center' => $options['center'], 'center' => $options['center'],
'role' => $options['role'] 'role' => $options['role']
]); ])
} ->add('scope', ScopePickerType::class, [
'center' => $options['center'],
if ($activityType->isVisible('reasons')) { 'role' => $options['role']
$builder->add('reasons', EntityType::class, [ ])
'label' => $activityType->getLabel('reasons'), ->add('reasons', TranslatableActivityReason::class, array(
'required' => $activityType->isRequired('reasons'),
'class' => ActivityReason::class,
'multiple' => true, 'multiple' => true,
'choice_label' => function (ActivityReason $activityReason) { 'required' => false,
return $this->translatableStringHelper->localize($activityReason->getName()); ))
}, ->add('type', TranslatableActivityType::class, array(
'attr' => array('class' => 'select2 '), 'placeholder' => 'Choose a type',
'query_builder' => function (EntityRepository $er) { 'active_only' => true
return $er->createQueryBuilder('a') ))
->where('a.active = true'); ->add('comment', CommentType::class, [
}, 'required' => false,
]); ])
} ;
if ($activityType->isVisible('comment')) { $builder->get('durationTime')
$builder->add('comment', CommentType::class, [
'label' => empty($activityType->getLabel('comment'))
? 'activity.comment' : $activityType->getLabel('comment'),
'required' => $activityType->isRequired('comment'),
]);
}
if ($activityType->isVisible('persons')) {
$builder->add('persons', HiddenType::class);
$builder->get('persons')
->addModelTransformer(new CallbackTransformer(
function (iterable $personsAsIterable): string {
$personIds = [];
foreach ($personsAsIterable as $value) {
$personIds[] = $value->getId();
}
return implode(',', $personIds);
},
function (?string $personsAsString): array {
return array_map(
fn(string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString)
);
}
))
;
}
if ($activityType->isVisible('thirdParties')) {
$builder->add('thirdParties', HiddenType::class);
$builder->get('thirdParties')
->addModelTransformer(new CallbackTransformer(
function (iterable $thirdpartyAsIterable): string {
$thirdpartyIds = [];
foreach ($thirdpartyAsIterable as $value) {
$thirdpartyIds[] = $value->getId();
}
return implode(',', $thirdpartyIds);
},
function (?string $thirdpartyAsString): array {
return array_map(
fn(string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
explode(',', $thirdpartyAsString)
);
}
))
;
}
if ($activityType->isVisible('documents')) {
$builder->add('documents', ChillCollectionType::class, [
'entry_type' => StoredObjectType::class,
'label' => $activityType->getLabel('documents'),
'required' => $activityType->isRequired('documents'),
'allow_add' => true,
'button_add_label' => 'activity.Insert a document',
'button_remove_label' => 'activity.Remove a document'
]);
}
if ($activityType->isVisible('users')) {
$builder->add('users', HiddenType::class);
$builder->get('users')
->addModelTransformer(new CallbackTransformer(
function (iterable $usersAsIterable): string {
$userIds = [];
foreach ($usersAsIterable as $value) {
$userIds[] = $value->getId();
}
return implode(',', $userIds);
},
function (?string $usersAsString): array {
return array_map(
fn(string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
explode(',', $usersAsString)
);
}
))
;
}
if ($activityType->isVisible('emergency')) {
$builder->add('emergency', CheckboxType::class, [
'label' => $activityType->getLabel('emergency'),
'required' => $activityType->isRequired('emergency'),
]);
}
if ($activityType->isVisible('sentReceived')) {
$builder->add('sentReceived', ChoiceType::class, [
'label' => $activityType->getLabel('sentReceived'),
'required' => $activityType->isRequired('sentReceived'),
'choices' => [
'Sent' => Activity::SENTRECEIVED_SENT,
'Received' => Activity::SENTRECEIVED_RECEIVED,
],
]);
}
foreach (['durationTime', 'travelTime'] as $fieldName) {
if (!$activityType->isVisible($fieldName)) {
continue;
}
$builder->get($fieldName)
->addModelTransformer($durationTimeTransformer); ->addModelTransformer($durationTimeTransformer);
$builder->get($fieldName)
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $formEvent) use (
$timeChoices,
$builder,
$durationTimeTransformer,
$durationTimeOptions,
$fieldName
) {
// set the timezone to GMT, and fix the difference between current and GMT
// the datetimetransformer will then handle timezone as GMT
$timezoneUTC = new \DateTimeZone('GMT');
/* @var $data \DateTime */
$data = $formEvent->getData() === NULL ?
\DateTime::createFromFormat('U', 300) :
$formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC);
$data->add(new \DateInterval('PT'.$seconds.'S'));
// test if the timestamp is in the choices. $builder->get('durationTime')
// If not, recreate the field with the new timestamp ->addEventListener(
if (!in_array($data->getTimestamp(), $timeChoices)) { FormEvents::PRE_SET_DATA,
// the data are not in the possible values. add them function(FormEvent $formEvent) use (
$timeChoices[$data->format('H:i')] = $data->getTimestamp(); $timeChoices,
$form = $builder->create($fieldName, ChoiceType::class, array_merge( $builder,
$durationTimeOptions, [ $durationTimeTransformer,
'choices' => $timeChoices, $durationTimeOptions
'auto_initialize' => false )
] {
)); // set the timezone to GMT, and fix the difference between current and GMT
$form->addModelTransformer($durationTimeTransformer); // the datetimetransformer will then handle timezone as GMT
$formEvent->getForm()->getParent()->add($form->getForm()); $timezoneUTC = new \DateTimeZone('GMT');
} /* @var $data \DateTime */
}); $data = $formEvent->getData() === NULL ?
} \DateTime::createFromFormat('U', 300) :
$formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC);
$data->add(new \DateInterval('PT'.$seconds.'S'));
// test if the timestamp is in the choices.
// If not, recreate the field with the new timestamp
if (!in_array($data->getTimestamp(), $timeChoices)) {
// the data are not in the possible values. add them
$timeChoices[$data->format('H:i')] = $data->getTimestamp();
$form = $builder->create(
'durationTime',
ChoiceType::class,
array_merge(
$durationTimeOptions,
array(
'choices' => $timeChoices,
'auto_initialize' => false
)
));
$form->addModelTransformer($durationTimeTransformer);
$formEvent->getForm()->getParent()->add($form->getForm());
}
});
} }
/**
* @param OptionsResolverInterface $resolver
public function configureOptions(OptionsResolver $resolver): void */
public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults([ $resolver->setDefaults(array(
'data_class' => Activity::class 'data_class' => 'Chill\ActivityBundle\Entity\Activity'
]); ));
$resolver $resolver
->setRequired(['center', 'role', 'activityType', 'accompanyingPeriod']) ->setRequired(array('center', 'role'))
->setAllowedTypes('center', ['null', 'Chill\MainBundle\Entity\Center']) ->setAllowedTypes('center', 'Chill\MainBundle\Entity\Center')
->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role') ->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role')
->setAllowedTypes('activityType', \Chill\ActivityBundle\Entity\ActivityType::class) ;
->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null'])
;
} }
public function getBlockPrefix(): string /**
* @return string
*/
public function getBlockPrefix()
{ {
return 'chill_activitybundle_activity'; return 'chill_activitybundle_activity';
} }

View File

@@ -1,39 +0,0 @@
<?php
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeCategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, array(
'choices' => array(
'Yes' => true,
'No' => false
),
'expanded' => true
))
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => ActivityTypeCategory::class
));
}
}

View File

@@ -2,13 +2,7 @@
namespace Chill\ActivityBundle\Form; namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\ActivityTypeCategory;
use Chill\ActivityBundle\Form\Type\ActivityFieldPresence;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@@ -16,56 +10,38 @@ use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ActivityTypeType extends AbstractType class ActivityTypeType extends AbstractType
{ {
private TranslatableStringHelper $translatableStringHelper; /**
* @param FormBuilderInterface $builder
public function __construct(TranslatableStringHelper $translatableStringHelper) * @param array $options
{ */
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder $builder
->add('name', TranslatableStringFormType::class) ->add('name', TranslatableStringFormType::class)
->add('active', ChoiceType::class, [ ->add('active', ChoiceType::class, array(
'choices' => [ 'choices' => array(
'Yes' => true, 'Yes' => true,
'No' => false 'No' => false
], ),
'expanded' => true 'expanded' => true
]) ));
->add('category', EntityType::class, [
'class' => ActivityTypeCategory::class,
'choice_label' => function (ActivityTypeCategory $activityTypeCategory) {
return $this->translatableStringHelper->localize($activityTypeCategory->getName());
},
])
->add('ordering', NumberType::class, [
'required' => true,
'scale' => 5
])
;
$fields = [
'persons', 'user', 'date', 'place', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'sentReceived', 'documents',
'emergency', 'accompanyingPeriod', 'socialData', 'users'
];
foreach ($fields as $field) {
$builder
->add($field.'Visible', ActivityFieldPresence::class)
->add($field.'Label', TextType::class, [
'required' => false,
'empty_data' => '',
]);
}
} }
/**
* @param OptionsResolverInterface $resolver
*/
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults(array( $resolver->setDefaults(array(
'data_class' => \Chill\ActivityBundle\Entity\ActivityType::class 'data_class' => 'Chill\ActivityBundle\Entity\ActivityType'
)); ));
} }
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_activitybundle_activitytype';
}
} }

View File

@@ -1,29 +0,0 @@
<?php
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityFieldPresence extends AbstractType
{
public function getParent()
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'choices' => [
'Invisible' => ActivityType::FIELD_INVISIBLE,
'Optional' => ActivityType::FIELD_OPTIONAL,
'Required' => ActivityType::FIELD_REQUIRED,
],
)
);
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace Chill\ActivityBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
{
protected TokenStorageInterface $tokenStorage;
protected AuthorizationHelper $authorizationHelper;
protected TranslatorInterface $translator;
public function __construct(
TokenStorageInterface $tokenStorage,
AuthorizationHelper $authorizationHelper,
TranslatorInterface $translator
) {
$this->translator = $translator;
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
}
public static function getMenuIds(): array
{
return ['accompanyingCourse'];
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
$period = $parameters['accompanyingCourse'];
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
$menu->addChild($this->translator->trans('Activity'), [
'route' => 'chill_activity_activity_list',
'routeParameters' => [
'accompanying_period_id' => $period->getId(),
]])
->setExtras(['order' => 40]);
}
}
}

View File

@@ -0,0 +1,88 @@
<?php
/*
*
*/
namespace Chill\ActivityBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Role\Role;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class MenuBuilder implements LocalMenuBuilderInterface
{
/**
*
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
*
* @var TranslatorInterface
*/
protected $translator;
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
public function __construct(
TokenStorageInterface $tokenStorage,
TranslatorInterface $translator,
AuthorizationHelper $authorizationHelper
) {
$this->tokenStorage = $tokenStorage;
$this->translator = $translator;
$this->authorizationHelper = $authorizationHelper;
}
public function buildMenu($menuId, MenuItem $menu, array $parameters)
{
/* @var $person \Chill\PersonBundle\Entity\Person */
$person = $parameters['person'];
$user = $this->tokenStorage->getToken()->getUser();
$roleSee = new Role(ActivityVoter::SEE);
$roleAdd = new Role(ActivityVoter::CREATE);
if ($this->authorizationHelper->userHasAccess($user, $person, $roleSee)) {
$menu->addChild($this->translator->trans('Activity list'), [
'route' => 'chill_activity_activity_list',
'routeParameters' => [
'person_id' => $person->getId()
]
])
->setExtras([
'order' => 201
]);
}
if ($this->authorizationHelper->userHasAccess($user, $person, $roleAdd)) {
$menu->addChild($this->translator->trans('Add a new activity'), [
'route' => 'chill_activity_activity_new',
'routeParameters' => [
'person_id' => $person->getId()
]
])
->setExtras([
'order' => 200
]);
}
}
public static function getMenuIds(): array
{
return [ 'person' ];
}
}

View File

@@ -15,7 +15,8 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Chill\ActivityBundle\Menu; namespace Chill\ActivityBundle\Menu;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem; use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
@@ -64,6 +65,15 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
->setExtra('order', 201) ->setExtra('order', 201)
; ;
} }
if ($this->authorizationChecker->isGranted(ActivityVoter::CREATE, $person)) {
$menu->addChild(
$this->translator->trans('Add a new activity'), [
'route' => 'chill_activity_activity_new',
'routeParameters' => [ 'person_id' => $person->getId() ],
])
->setExtra('order', 200)
;
}
} }
public static function getMenuIds(): array public static function getMenuIds(): array

View File

@@ -1,24 +0,0 @@
<?php
namespace Chill\ActivityBundle\Notification;
use Chill\MainBundle\Entity\Notification;
use Chill\ActivityBundle\Entity\Activity;
final class ActivityNotificationRenderer
{
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() == Activity::class;
}
public function getTemplate()
{
return '@ChillActivity/Activity/showInNotification.html.twig';
}
public function getTemplateData(Notification $notification)
{
return ['notification' => $notification];
}
}

View File

@@ -23,8 +23,6 @@
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter; use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
@@ -35,10 +33,9 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface final class ActivityACLAwareRepository
{ {
private AuthorizationHelper $authorizationHelper; private AuthorizationHelper $authorizationHelper;
@@ -48,63 +45,16 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
private EntityManagerInterface $em; private EntityManagerInterface $em;
private Security $security;
private CenterResolverDispatcher $centerResolverDispatcher;
public function __construct( public function __construct(
AuthorizationHelper $authorizationHelper, AuthorizationHelper $authorizationHelper,
CenterResolverDispatcher $centerResolverDispatcher,
TokenStorageInterface $tokenStorage, TokenStorageInterface $tokenStorage,
ActivityRepository $repository, ActivityRepository $repository,
EntityManagerInterface $em, EntityManagerInterface $em
Security $security
) { ) {
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->centerResolverDispatcher = $centerResolverDispatcher;
$this->tokenStorage = $tokenStorage; $this->tokenStorage = $tokenStorage;
$this->repository = $repository; $this->repository = $repository;
$this->em = $em; $this->em = $em;
$this->security = $security;
}
/**
* @param Person $person
* @param string $role
* @param int|null $start
* @param int|null $limit
* @param array $orderBy
* @return array|Activity[]
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
{
$user = $this->security->getUser();
$center = $this->centerResolverDispatcher->resolveCenter($person);
if (0 === count($orderBy)) {
$orderBy = ['date' => 'DESC'];
}
$reachableScopes = $this->authorizationHelper
->getReachableCircles($user, $role, $center);
return $this->em->getRepository(Activity::class)
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
;
}
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
{
$user = $this->security->getUser();
$center = $this->centerResolverDispatcher->resolveCenter($period);
if (0 === count($orderBy)) {
$orderBy = ['date' => 'DESC'];
}
$scopes = $this->authorizationHelper
->getReachableCircles($user, $role, $center);
return $this->em->getRepository(Activity::class)
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
} }
public function queryTimelineIndexer(string $context, array $args = []): array public function queryTimelineIndexer(string $context, array $args = []): array
@@ -131,7 +81,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$metadataActivity = $this->em->getClassMetadata(Activity::class); $metadataActivity = $this->em->getClassMetadata(Activity::class);
$metadataPerson = $this->em->getClassMetadata(Person::class); $metadataPerson = $this->em->getClassMetadata(Person::class);
$associationMapping = $metadataActivity->getAssociationMapping('person'); $associationMapping = $metadataActivity->getAssociationMapping('person');
return $metadataActivity->getTableName().' JOIN ' return $metadataActivity->getTableName().' JOIN '
.$metadataPerson->getTableName().' ON ' .$metadataPerson->getTableName().' ON '
.$metadataPerson->getTableName().'.'. .$metadataPerson->getTableName().'.'.
@@ -145,7 +95,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
{ {
$where = ''; $where = '';
$parameters = []; $parameters = [];
$metadataActivity = $this->em->getClassMetadata(Activity::class); $metadataActivity = $this->em->getClassMetadata(Activity::class);
$metadataPerson = $this->em->getClassMetadata(Person::class); $metadataPerson = $this->em->getClassMetadata(Person::class);
$activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name']; $activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name'];
@@ -155,20 +105,20 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
// acls: // acls:
$role = new Role(ActivityVoter::SEE); $role = new Role(ActivityVoter::SEE);
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(), $reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
$role); $role);
if (count($reachableCenters) === 0) { if (count($reachableCenters) === 0) {
// insert a dummy condition // insert a dummy condition
return 'FALSE = TRUE'; return 'FALSE = TRUE';
} }
if ($context === 'person') { if ($context === 'person') {
// we start with activities having the person_id linked to person // we start with activities having the person_id linked to person
$where .= sprintf('%s = ? AND ', $activityToPerson); $where .= sprintf('%s = ? AND ', $activityToPerson);
$parameters[] = $person->getId(); $parameters[] = $person->getId();
} }
// we add acl (reachable center and scopes) // we add acl (reachable center and scopes)
$where .= '('; // first loop for the for centers $where .= '('; // first loop for the for centers
$centersI = 0; // like centers#i $centersI = 0; // like centers#i
@@ -181,7 +131,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center); $reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center);
// we get the ids for those scopes // we get the ids for those scopes
$reachablesScopesId = array_map( $reachablesScopesId = array_map(
function(Scope $scope) { return $scope->getId(); }, function(Scope $scope) { return $scope->getId(); },
$reachableScopes $reachableScopes
); );
@@ -212,7 +162,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
} }
// close loop for centers // close loop for centers
$where .= ')'; $where .= ')';
return [$where, $parameters]; return [$where, $parameters];
} }

View File

@@ -1,19 +0,0 @@
<?php
namespace Chill\ActivityBundle\Repository;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
interface ActivityACLAwareRepositoryInterface
{
/**
* @return array|Activity[]
*/
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
/**
* @return array|Activity[]
*/
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
}

View File

@@ -23,8 +23,6 @@
namespace Chill\ActivityBundle\Repository; namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
@@ -40,86 +38,5 @@ class ActivityRepository extends ServiceEntityRepository
{ {
parent::__construct($registry, Activity::class); parent::__construct($registry, Activity::class);
} }
/**
* @param $person
* @param array $scopes
* @param string[] $orderBy
* @param int $limit
* @param int $offset
* @return array|Activity[]
*/
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
{
$qb = $this->createQueryBuilder('a');
$qb->select('a');
$qb
->where($qb->expr()->in('a.scope', ':scopes'))
->setParameter('scopes', $scopes)
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('a.person', ':person'),
':person MEMBER OF a.persons'
)
)
->setParameter('person', $person)
;
foreach ($orderBy as $k => $dir) {
$qb->addOrderBy('a.'.$k, $dir);
}
$qb->setMaxResults($limit)->setFirstResult($offset);
return $qb->getQuery()
->getResult();
}
/**
* @param AccompanyingPeriod $period
* @param array $scopes
* @param int|null $limit
* @param int|null $offset
* @param array|string[] $orderBy
* @return array|Activity[]
*/
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
{
$qb = $this->createQueryBuilder('a');
$qb->select('a');
if (!$allowNullScope) {
$qb
->where($qb->expr()->in('a.scope', ':scopes'))
->setParameter('scopes', $scopes)
;
} else {
$qb
->where(
$qb->expr()->orX(
$qb->expr()->in('a.scope', ':scopes'),
$qb->expr()->isNull('a.scope')
)
)
->setParameter('scopes', $scopes)
;
}
$qb
->andWhere(
$qb->expr()->eq('a.accompanyingPeriod', ':period')
)
->setParameter('period', $period)
;
foreach ($orderBy as $k => $dir) {
$qb->addOrderBy('a.'.$k, $dir);
}
$qb->setMaxResults($limit)->setFirstResult($offset);
return $qb->getQuery()
->getResult();
}
} }

View File

@@ -0,0 +1,10 @@
@import '~ChillMainSass/custom/config/colors';
@import '~ChillMainSass/custom/mixins/entity';
.chill-entity.chill-entity__activity-reason {
@include entity($chill-pink, white);
}
.activity {
color: $chill-green;
}

View File

@@ -1,142 +0,0 @@
// Access to Bootstrap variables and mixins
@import '~ChillMainAssets/module/bootstrap/shared';
// activity creation first step: select type page
div.new-activity-select-type {
div.activity-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
gap: 12px;
div.bloc {
width: 200px;
align-self: flex-end;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
// exceptions for flex-table in list-records
div.activity-list {
div.flex-table {
div.item-bloc {
div.item-row.main {
div.item-col {
&:first-child {
flex-basis: 15%;
}
ul.list-content {
li.social-issues, li.social-actions {
.badge-primary {
font-variant: small-caps;
font-weight: bold;
font-size: 88%;
margin-bottom: 0.2em;
}
}
li.social-issues .badge-primary {
background-color: $orange;
}
li.social-actions .badge-primary {
background-color: $green;
}
}
}
}
div.item-row.comment {
margin-left: 15%;
blockquote.chill-user-quote {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
}
div.item-row.details {
margin-left: 15%;
// override flex-bloc to adapt in list
// TODO refund this
div.accompanyingCourse.flex-bloc.concerned-groups {
margin: 0;
width: 100%;
justify-content: space-around;
div.item-bloc {
box-shadow: unset;
padding: 0;
flex-basis: 25%;
div.item-row {
flex-direction: column;
div.item-col {
&:first-child {
width: unset;
}
&:last-child {
border-top: 0;
margin-top: 0;
padding-top: 0;
ul.list-content {
padding: 0;
}
}
}
}
}
}
}
ul.list-content {
list-style-type: none;
padding-left: 1em;
margin: 0 0;
li {
margin-bottom: 0.2em;
}
}
}
div.duration {
font-size: smaller;
padding-left: 1em;
margin-top: 1em;
}
}
}
// exceptions for flex-bloc in concerned-groups
div.flex-bloc.concerned-groups {
margin-top: 1em;
div.item-bloc {
flex-grow: 0; flex-shrink: 0; flex-basis: 25%; //4 blocs
ul.list-content {
list-style-type: none;
padding-left: 0;
li {
margin-bottom: 0.2em;
a {
color: $white;
cursor: pointer;
&:hover {
color: #ffffffab;
}
}
}
}
}
&.person div.item-bloc {
flex-basis: 33%; //3 blocs
}
}
/// CHILL ENTITY RENDER BOX
.chill-entity {
/// ACTIVITY-REASON
&.entity-activity-reason {
margin-right: 0.3em;
font-size: 120%;
}
}

View File

@@ -1 +0,0 @@
require('./chillactivity.scss');

View File

@@ -0,0 +1 @@
require('./activity/activity.scss');

View File

@@ -1,17 +0,0 @@
<template>
<concerned-groups></concerned-groups>
<social-issues-acc></social-issues-acc>
</template>
<script>
import ConcernedGroups from './components/ConcernedGroups.vue';
import SocialIssuesAcc from './components/SocialIssuesAcc.vue';
export default {
name: "App",
components: {
ConcernedGroups,
SocialIssuesAcc
}
}
</script>

View File

@@ -1,18 +0,0 @@
import { getSocialIssues } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api.js';
/*
* Load socialActions by socialIssue (id)
*/
const getSocialActionByIssue = (id) => {
const url = `/api/1.0/person/social/social-action/by-social-issue/${id}.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
export {
getSocialIssues,
getSocialActionByIssue
};

View File

@@ -1,185 +0,0 @@
<template>
<teleport to="#add-persons">
<div class="flex-bloc concerned-groups" :class="getContext">
<persons-bloc
v-for="bloc in contextPersonsBlocs"
v-bind:key="bloc.key"
v-bind:bloc="bloc"
v-bind:setPersonsInBloc="setPersonsInBloc">
</persons-bloc>
</div>
<div v-if="getContext === 'accompanyingCourse' && filterSuggestedPersons.length > 0">
<ul>
<li v-for="p in filterSuggestedPersons" @click="addNewPerson(p)">
{{ p.text }}
</li>
</ul>
</div>
<add-persons
buttonTitle="activity.add_persons"
modalTitle="activity.add_persons"
v-bind:key="addPersons.key"
v-bind:options="addPersons.options"
@addNewPersons="addNewPersons"
ref="addPersons">
</add-persons>
</teleport>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import PersonsBloc from './ConcernedGroups/PersonsBloc.vue';
export default {
name: "ConcernedGroups",
components: {
AddPersons,
PersonsBloc
},
data() {
return {
personsBlocs: [
{ key: 'persons',
title: 'activity.bloc_persons',
persons: [],
included: false
},
{ key: 'personsAssociated',
title: 'activity.bloc_persons_associated',
persons: [],
included: false
},
{ key: 'personsNotAssociated',
title: 'activity.bloc_persons_not_associated',
persons: [],
included: false
},
{ key: 'thirdparty',
title: 'activity.bloc_thirdparty',
persons: [],
included: true
},
{ key: 'users',
title: 'activity.bloc_users',
persons: [],
included: true
},
],
addPersons: {
key: 'activity',
options: {
type: ['person', 'thirdparty', 'user'], // TODO add 'user'
priority: null,
uniq: false,
}
}
}
},
computed: {
...mapState({
persons: state => state.activity.persons,
thirdParties: state => state.activity.thirdParties,
users: state => state.activity.users,
accompanyingCourse: state => state.activity.accompanyingPeriod
}),
...mapGetters([
'filterSuggestedPersons'
]),
getContext() {
return (this.accompanyingCourse) ? "accompanyingCourse" : "person";
},
contextPersonsBlocs() {
return this.personsBlocs.filter(bloc => bloc.included !== false);
}
},
mounted() {
this.setPersonsInBloc();
},
methods: {
setPersonsInBloc() {
let groups;
if (this.accompanyingCourse) {
groups = this.splitPersonsInGroups();
}
this.personsBlocs.forEach(bloc => {
if (this.accompanyingCourse) {
switch (bloc.key) {
case 'personsAssociated':
bloc.persons = groups.personsAssociated;
bloc.included = true;
break;
case 'personsNotAssociated':
bloc.persons = groups.personsNotAssociated;
bloc.included = true;
break;
}
} else {
switch (bloc.key) {
case 'persons':
bloc.persons = this.persons;
bloc.included = true;
break;
}
}
switch (bloc.key) {
case 'thirdparty':
bloc.persons = this.thirdParties;
break;
case 'users':
bloc.persons = this.users;
break;
}
}, groups);
},
splitPersonsInGroups() {
let personsAssociated = [];
let personsNotAssociated = this.persons;
let participations = this.getCourseParticipations();
this.persons.forEach(person => {
participations.forEach(participation => {
if (person.id === participation.id) {
//console.log(person.id);
personsAssociated.push(person);
personsNotAssociated = personsNotAssociated.filter(p => p !== person);
}
});
});
return {
'personsAssociated': personsAssociated,
'personsNotAssociated': personsNotAssociated
};
},
getCourseParticipations() {
let participations = [];
this.accompanyingCourse.participations.forEach(participation => {
if (!participation.endDate) {
participations.push(participation.person);
}
});
return participations;
},
addNewPersons({ selected, modal }) {
console.log('@@@ CLICK button addNewPersons', selected);
selected.forEach(function(item) {
this.$store.dispatch('addPersonsInvolved', item);
}, this
);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
this.setPersonsInBloc();
},
addNewPerson(person) {
this.$store.dispatch('addPersonsInvolved', { result: person, type: 'person' });
this.setPersonsInBloc();
},
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,29 +0,0 @@
<template>
<li>
<span class="badge bg-primary" :title="person.text">
<span class="chill_denomination">
{{ textCutted }}
</span>
<a class="fa fa-fw fa-times"
@click.prevent="$emit('remove', person)">
</a>
</span>
</li>
</template>
<script>
export default {
name: "PersonBadge",
props: ['person'],
computed: {
textCutted() {
let more = (this.person.text.length > 15) ?'…' : '';
return this.person.text.slice(0,15) + more;
}
},
emits: ['remove'],
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,41 +0,0 @@
<template>
<div class="item-bloc">
<div class="item-row">
<div class="item-col">
<h4>{{ $t(bloc.title) }}</h4>
</div>
<div class="item-col">
<ul class="list-content">
<person-badge
v-for="person in bloc.persons"
v-bind:key="person.id"
v-bind:person="person"
@remove="removePerson">
</person-badge>
</ul>
</div>
</div>
</div>
</template>
<script>
import PersonBadge from './PersonBadge.vue';
export default {
name:"PersonsBloc",
components: {
PersonBadge
},
props: ['bloc', 'setPersonsInBloc'],
methods: {
removePerson(item) {
console.log('@@ CLICK remove person: item', item);
this.$store.dispatch('removePersonInvolved', item);
this.setPersonsInBloc();
}
}
}
</script>
<style lang="scss">
</style>

View File

@@ -1,214 +0,0 @@
<template>
<teleport to="#social-issues-acc">
<div class="mb-3 row">
<div class="col-4">
<label class="col-form-label">{{ $t('activity.social_issues') }}</label>
</div>
<div class="col-8">
<check-social-issue
v-for="issue in socialIssuesList"
v-bind:key="issue.id"
v-bind:issue="issue"
v-bind:selection="socialIssuesSelected"
@updateSelected="updateIssuesSelected">
</check-social-issue>
<div class="my-3">
<VueMultiselect
name="otherIssues"
label="text"
track-by="id"
open-direction="bottom"
v-bind:close-on-select="true"
v-bind:preserve-search="false"
v-bind:reset-after="true"
v-bind:hide-selected="true"
v-bind:taggable="false"
v-bind:multiple="false"
v-bind:searchable="true"
v-bind:allow-empty="true"
v-bind:show-labels="false"
v-bind:loading="issueIsLoading"
v-bind:placeholder="$t('activity.choose_other_social_issue')"
v-bind:options="socialIssuesOther"
v-model="value"
@select="addIssueInList">
</VueMultiselect>
</div>
</div>
</div>
<div class="mb-3 row">
<div class="col-4">
<label class="col-form-label">{{ $t('activity.social_actions') }}</label>
</div>
<div class="col-8">
<div v-if="actionIsLoading === true">
<i class="chill-green fa fa-circle-o-notch fa-spin fa-lg"></i>
</div>
<check-social-action
v-if="socialIssuesSelected.length || socialActionsSelected.length"
v-for="action in socialActionsList"
v-bind:key="action.id"
v-bind:action="action"
v-bind:selection="socialActionsSelected"
@updateSelected="updateActionsSelected">
</check-social-action>
<span v-else class="inline-choice chill-no-data-statement mt-3">
{{ $t('activity.select_first_a_social_issue') }}
</span>
</div>
</div>
</teleport>
</template>
<script>
import { readonly } from 'vue';
import VueMultiselect from 'vue-multiselect';
import CheckSocialIssue from './SocialIssuesAcc/CheckSocialIssue.vue';
import CheckSocialAction from './SocialIssuesAcc/CheckSocialAction.vue';
import { getSocialIssues, getSocialActionByIssue } from '../api.js';
export default {
name: "SocialIssuesAcc",
components: {
CheckSocialIssue,
CheckSocialAction,
VueMultiselect
},
data() {
return {
issueIsLoading: false,
actionIsLoading: false
}
},
computed: {
socialIssuesList() {
return this.$store.state.activity.accompanyingPeriod.socialIssues;
},
socialIssuesSelected() {
return this.$store.state.activity.socialIssues;
},
socialIssuesOther() {
return this.$store.state.socialIssuesOther;
},
socialActionsList() {
return this.$store.state.socialActionsList;
},
socialActionsSelected() {
return this.$store.state.activity.socialActions;
}
},
mounted() {
/* Load others issues in multiselect
*/
this.issueIsLoading = true;
getSocialIssues().then(response => new Promise((resolve, reject) => {
this.$store.commit('updateIssuesOther', response.results);
/* Add in list the issues already associated (if not yet listed)
*/
this.socialIssuesSelected.forEach(issue => {
if (this.socialIssuesList.filter(i => i.id === issue.id).length !== 1) {
this.$store.commit('addIssueInList', issue);
}
}, this);
/* Remove from multiselect the issues that are not yet in checkbox list
*/
this.socialIssuesList.forEach(issue => {
this.$store.commit('removeIssueInOther', issue);
}, this);
/* Filter issues
*/
this.$store.commit('filterList', 'issues');
/* Add in list the actions already associated (if not yet listed)
*/
this.socialActionsSelected.forEach(action => {
this.$store.commit('addActionInList', action);
}, this);
/* Filter issues
*/
this.$store.commit('filterList', 'actions');
this.issueIsLoading = false;
resolve();
}));
},
methods: {
/* When choosing an issue in multiselect, add it in checkboxes (as selected),
remove it from multiselect, and add socialActions concerned
*/
addIssueInList(value) {
//console.log('addIssueInList', value);
this.$store.commit('addIssueInList', value);
this.$store.commit('removeIssueInOther', value);
this.$store.dispatch('addIssueSelected', value);
this.updateActionsList();
},
/* Update value for selected issues checkboxes
*/
updateIssuesSelected(issues) {
//console.log('updateIssuesSelected', issues);
this.$store.dispatch('updateIssuesSelected', issues);
this.updateActionsList();
},
/* Update value for selected actions checkboxes
*/
updateActionsSelected(actions) {
//console.log('updateActionsSelected', actions);
this.$store.dispatch('updateActionsSelected', actions);
},
/* Add socialActions concerned: after reset, loop on each issue selected
to get social actions concerned
*/
updateActionsList() {
//console.log('updateActionsList');
this.resetActionsList();
this.socialIssuesSelected.forEach(item => {
this.actionIsLoading = true;
getSocialActionByIssue(item.id)
.then(actions => new Promise((resolve, reject) => {
actions.results.forEach(action => {
this.$store.commit('addActionInList', action);
}, this);
this.$store.commit('filterList', 'actions');
this.actionIsLoading = false;
resolve();
}));
}, this);
},
/* Reset socialActions List: flush list and restore selected actions
*/
resetActionsList() {
this.$store.commit('resetActionsList');
this.socialActionsSelected.forEach(item => {
this.$store.commit('addActionInList', item);
}, this);
}
}
}
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style lang="scss">
span.multiselect__single {
display: none !important;
}
</style>

View File

@@ -1,36 +0,0 @@
<template>
<span class="inline-choice">
<div class="form-check">
<input class="form-check-input"
type="checkbox"
v-model="selected"
name="action"
v-bind:id="action.id"
v-bind:value="action"
/>
<label class="form-check-label" v-bind:for="action.id">
{{ action.text }}
</label>
</div>
</span>
</template>
<script>
export default {
name: "CheckSocialAction",
props: [ 'action', 'selection' ],
emits: [ 'updateSelected' ],
computed: {
selected: {
set(value) {
this.$emit('updateSelected', value);
},
get() {
return this.selection;
}
}
}
}
</script>

View File

@@ -1,36 +0,0 @@
<template>
<span class="inline-choice">
<div class="form-check">
<input class="form-check-input"
type="checkbox"
v-model="selected"
name="issue"
v-bind:id="issue.id"
v-bind:value="issue"
/>
<label class="form-check-label" v-bind:for="issue.id">
{{ issue.text }}
</label>
</div>
</span>
</template>
<script>
export default {
name: "CheckSocialIssue",
props: [ 'issue', 'selection' ],
emits: [ 'updateSelected' ],
computed: {
selected: {
set(value) {
this.$emit('updateSelected', value);
},
get() {
return this.selection;
}
}
}
}
</script>

View File

@@ -1,27 +0,0 @@
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n'
const appMessages = {
fr: {
activity: {
//
social_issues: "Problématiques sociales",
choose_other_social_issue: "Ajouter une autre problématique sociale...",
social_actions: "Actions d'accompagnement",
select_first_a_social_issue: "Sélectionnez d'abord une problématique sociale",
//
add_persons: "Ajouter des personnes concernées",
bloc_persons: "Usagers",
bloc_persons_associated: "Usagers du parcours",
bloc_persons_not_associated: "Tiers non-pro.",
bloc_thirdparty: "Tiers professionnels",
bloc_users: "T(M)S",
}
}
}
Object.assign(appMessages.fr, personMessages.fr);
export {
appMessages
};

View File

@@ -1,16 +0,0 @@
import { createApp } from 'vue';
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
import { appMessages } from './i18n'
import store from './store'
import App from './App.vue';
const i18n = _createI18n(appMessages);
const app = createApp({
template: `<app></app>`,
})
.use(store)
.use(i18n)
.component('app', App)
.mount('#activity');

View File

@@ -1,180 +0,0 @@
import 'es6-promise/auto';
import { createStore } from 'vuex';
const debug = process.env.NODE_ENV !== 'production';
//console.log('window.activity', window.activity);
const addIdToValue = (string, id) => {
let array = string ? string.split(',') : [];
array.push(id.toString());
let str = array.join();
return str;
};
const removeIdFromValue = (string, id) => {
let array = string.split(',');
array = array.filter(el => el !== id.toString());
let str = array.join();
return str;
};
const store = createStore({
strict: debug,
state: {
activity: window.activity,
socialIssuesOther: [],
socialActionsList: [],
},
getters: {
filterSuggestedPersons(state) {
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
return [];
}
let existingPersonIds = state.activity.persons.map(p => p.id);
return state.activity.accompanyingPeriod.participations.filter(p => p.endDate === null)
.map(p => p.person)
.filter(p => !existingPersonIds.includes(p.id))
}
},
mutations: {
// SocialIssueAcc
addIssueInList(state, issue) {
//console.log('add issue list', issue.id);
state.activity.accompanyingPeriod.socialIssues.push(issue);
},
addIssueSelected(state, issue) {
//console.log('add issue selected', issue.id);
state.activity.socialIssues.push(issue);
},
updateIssuesSelected(state, issues) {
//console.log('update issues selected', issues);
state.activity.socialIssues = issues;
},
updateIssuesOther(state, payload) {
//console.log('update issues other');
state.socialIssuesOther = payload;
},
removeIssueInOther(state, issue) {
//console.log('remove issue other', issue.id);
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
},
resetActionsList(state) {
//console.log('reset list actions');
state.socialActionsList = [];
},
addActionInList(state, action) {
//console.log('add action list', action.id);
state.socialActionsList.push(action);
},
updateActionsSelected(state, actions) {
//console.log('update actions selected', actions);
state.activity.socialActions = actions;
},
filterList(state, list) {
const filterList = (list) => {
// remove duplicates entries
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
// alpha sort
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
return list;
};
if (list === 'issues') {
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
}
if (list === 'actions') {
state.socialActionsList = filterList(state.socialActionsList);
}
},
// ConcernedGroups
addPersonsInvolved(state, payload) {
//console.log('### mutation addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
case 'person':
state.activity.persons.push(payload.result);
break;
case 'thirdparty':
state.activity.thirdParties.push(payload.result);
break;
case 'user':
state.activity.users.push(payload.result);
break;
};
},
removePersonInvolved(state, payload) {
//console.log('### mutation removePersonInvolved', payload.type);
switch (payload.type) {
case 'person':
state.activity.persons = state.activity.persons.filter(person => person !== payload);
break;
case 'thirdparty':
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
break;
case 'user':
state.activity.users = state.activity.users.filter(user => user !== payload);
break;
};
}
},
actions: {
addIssueSelected({ commit }, issue) {
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
commit('addIssueSelected', issue);
},
updateIssuesSelected({ commit }, payload) {
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
aSocialIssues.value = '';
payload.forEach(item => {
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
});
commit('updateIssuesSelected', payload);
},
updateActionsSelected({ commit }, payload) {
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
aSocialActions.value = '';
payload.forEach(item => {
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
});
commit('updateActionsSelected', payload);
},
addPersonsInvolved({ commit }, payload) {
//console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
case 'person':
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
break;
case 'thirdparty':
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
break;
case 'user':
let aUsers = document.getElementById("chill_activitybundle_activity_users");
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
break;
};
commit('addPersonsInvolved', payload);
},
removePersonInvolved({ commit }, payload) {
//console.log('### action removePersonInvolved', payload);
switch (payload.type) {
case 'person':
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
break;
case 'thirdparty':
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
break;
case 'user':
let aUsers = document.getElementById("chill_activitybundle_activity_users");
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
break;
};
commit('removePersonInvolved', payload);
}
}
});
export default store;

View File

@@ -1,103 +0,0 @@
{% macro href(pathname, key, value) %}
{% set parms = { (key): value } %}
{{ path(pathname, parms) }}
{% endmacro %}
{% if context == 'person' %}
{% set blocs = [
{ 'title': 'Others persons'|trans,
'items': entity.persons,
'path' : 'chill_person_view',
'key' : 'person_id'
},
{ 'title': 'Third parties'|trans,
'items': entity.thirdParties,
'path' : 'chill_3party_3party_show',
'key' : 'thirdparty_id'
},
{ 'title': 'Users concerned'|trans,
'items': entity.users,
'path' : 'admin_user_show',
'key' : 'id'
},
] %}
{% else %}
{% set blocs = [
{ 'title': 'Persons in accompanying course'|trans,
'items': entity.personsAssociated,
'path' : 'chill_person_view',
'key' : 'person_id'
},
{ 'title': 'Third persons'|trans,
'items': entity.personsNotAssociated,
'path' : 'chill_person_view',
'key' : 'person_id'
},
{ 'title': 'Third parties'|trans,
'items': entity.thirdParties,
'path' : 'chill_3party_3party_show',
'key' : 'thirdparty_id'
},
{ 'title': 'Users concerned'|trans,
'items': entity.users,
'path' : 'admin_user_show',
'key' : 'id'
},
] %}
{% endif %}
{% if (with_display == 'bloc') %}
<div class="{{ context }} flex-bloc concerned-groups">
{% for bloc in blocs %}
<div class="item-bloc">
<div class="item-row">
<div class="item-col">
<h4>{{ bloc.title }}</h4>
</div>
<div class="item-col">
<ul class="list-content">
{% for item in bloc.items %}
<li>
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% if (with_display == 'row') %}
<div class="concerned-groups">
{% for bloc in blocs %}
<div class="group">
{% if bloc.items|length > 0 %}
<h4>{{ bloc.title }}</h4>
<ul class="list-content">
{% for item in bloc.items %}
<li>
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}

View File

@@ -1,4 +1,4 @@
{% extends "@ChillPerson/Person/layout.html.twig" %} {% extends "@ChillPerson/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %} {% set activeRouteKey = 'chill_activity_activity_list' %}
{% set person = activity.person %} {% set person = activity.person %}
@@ -6,6 +6,7 @@
{% block title 'Remove activity'|trans %} {% block title 'Remove activity'|trans %}
{% block personcontent %} {% block personcontent %}
{{ include('@ChillMain/Util/confirmation_template.html.twig', {{ include('@ChillMain/Util/confirmation_template.html.twig',
{ {
'title' : 'Remove activity'|trans, 'title' : 'Remove activity'|trans,
@@ -14,4 +15,5 @@
'cancel_parameters' : { 'person_id' : activity.person.id, 'id' : activity.id }, 'cancel_parameters' : { 'person_id' : activity.person.id, 'id' : activity.id },
'form' : delete_form 'form' : delete_form
} ) }} } ) }}
{% endblock %} {% endblock %}

View File

@@ -1,16 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title 'Remove activity'|trans %}
{% block content %}
{{ include('@ChillMain/Util/confirmation_template.html.twig',
{
'title' : 'Remove activity'|trans,
'confirm_question' : 'Are you sure you want to remove the activity about "%name%" ?'|trans({ '%name%' : accompanyingCourse.id } ),
'cancel_route' : 'chill_activity_activity_list',
'cancel_parameters' : { 'accompanying_course_id' : accompanyingCourse.id, 'id' : activity.id },
'form' : delete_form
} ) }}
{% endblock %}

View File

@@ -1,104 +1,59 @@
<h1>{{ "Update activity"|trans }}</h1> {#
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2> * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillPerson/layout.html.twig" %}
{{ form_start(edit_form) }} {% set activeRouteKey = 'chill_activity_activity_list' %}
{{ form_errors(edit_form) }}
{%- if edit_form.emergency is defined -%} {% block title 'Update activity'|trans %}
{{ form_row(edit_form.emergency) }}
{% endif %}
{%- if edit_form.sentReceived is defined -%} {% block personcontent %}
{{ form_row(edit_form.sentReceived) }} <h1>{{ "Update activity"|trans }}</h1>
{% endif %}
{{ form_start(edit_form) }}
{%- if edit_form.user is defined -%}
{{ form_row(edit_form.user) }} {{ form_row(edit_form.user) }}
{% endif %}
{%- if edit_form.scope is defined -%}
{{ form_row(edit_form.scope) }} {{ form_row(edit_form.scope) }}
{% endif %}
{%- if edit_form.socialIssues is defined -%} <h2>{{ 'Activity data'|trans }}</h2>
{{ form_row(edit_form.socialIssues) }}
{% endif %}
{%- if edit_form.socialActions is defined -%}
{{ form_row(edit_form.socialActions) }}
{% endif %}
<div id="social-issues-acc"></div>
{%- if edit_form.reasons is defined -%}
{{ form_row(edit_form.reasons) }}
{% endif %}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
{%- if edit_form.persons is defined -%}
{{ form_widget(edit_form.persons) }}
{% endif %}
{%- if edit_form.thirdParties is defined -%}
{{ form_widget(edit_form.thirdParties) }}
{% endif %}
{%- if edit_form.users is defined -%}
{{ form_widget(edit_form.users) }}
{% endif %}
<div id="add-persons"></div>
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
{%- if edit_form.date is defined -%}
{{ form_row(edit_form.date) }} {{ form_row(edit_form.date) }}
{% endif %}
{# TODO .. location #}
{%- if edit_form.durationTime is defined -%}
{{ form_row(edit_form.durationTime) }} {{ form_row(edit_form.durationTime) }}
{% endif %} {{ form_row(edit_form.type) }}
{%- if edit_form.travelTime is defined -%}
{{ form_row(edit_form.travelTime) }}
{% endif %}
{%- if edit_form.comment is defined -%}
{# TODO .. public and private #}
{{ form_row(edit_form.comment) }}
{% endif %}
{%- if edit_form.documents is defined -%}
{{ form_row(edit_form.documents) }}
{% endif %}
{%- if edit_form.attendee is defined -%}
{{ form_row(edit_form.attendee) }} {{ form_row(edit_form.attendee) }}
{% endif %} {{ form_row(edit_form.reasons) }}
{{ form_row(edit_form.comment) }}
{# TODO .. status #} {{ form_widget(edit_form) }}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': entity.person.id } ) }}" class="sc-button bt-cancel">
{{ 'Cancel'|trans }}
</a>
</li>
<li>
<button class="sc-button bt-update" type="submit">{{ 'Save activity'|trans }}</button>
</li>
</ul>
{{ form_end(edit_form) }}
{% set person_id = null %} {# {{ form(delete_form) }} #}
{% if entity.person %} {% endblock %}
{% set person_id = entity.person.id %}
{% endif %}
{% set accompanying_course_id = null %} {% block js %}
{% if accompanyingCourse %} <script type="text/javascript">
{% set accompanying_course_id = accompanyingCourse.id %} chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]', '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
{% endif %} </script>
{% endblock %}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-cancel">
{{ 'Cancel'|trans }}
</a>
</li>
<li>
<button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button>
</li>
</ul>
{{ form_end(edit_form) }}
{# {{ form(delete_form) }} #}

View File

@@ -1,33 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title 'Update activity'|trans %}
{% block content %}
<div class="activity-edit">
<div id="activity"></div> {# <=== vue component #}
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
</div>
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
});
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{% endblock %}

View File

@@ -1,47 +0,0 @@
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title 'Update activity'|trans %}
{% block personcontent %}
<div class="activity-edit">
<div id="activity"></div> {# <=== vue component #}
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
</div>
{% endblock %}
{% block js %}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
});
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{% endblock %}

View File

@@ -1,186 +1,87 @@
<div class="activity-list context-{{ context }}"> {#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillPerson/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
{% block personcontent %}
<h2>{{ 'Activity list' |trans }}</h2>
{% if activities|length == 0 %} {% if activities|length == 0 %}
<p class="chill-no-data-statement"> <p class="chill-no-data-statement">
{{ "There isn't any activities."|trans }} {{ "There isn't any activities."|trans }}
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-sm btn-create"></a> <a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create button-small"></a>
</p> </p>
{% else %} {% else %}
<div class="flex-table"> <table class="records_list">
{% for activity in activities %} <thead>
{% set t = activity.type %} <tr>
<div class="item-bloc"> <th class="chill-red">{{'Date' | trans }}</th>
<div class="item-row main"> <th class="chill-green">{{'Duration Time' | trans }}</th>
<div class="item-col"> <th class="chill-orange">{{'Reasons' | trans}}</th>
<th>{{'Type' | trans}}</th>
{% if activity.date %} <th>&nbsp;</th>
<h3>{{ activity.date|format_date('long') }}</h3> </tr>
{% endif %} </thead>
<tbody>
<div class="duration"> {% for activity in activities %}
{% if activity.durationTime and t.durationTimeVisible %} <tr>
<p> <td>{% if activity.date %}{{ activity.date|format_date('long') }}{% endif %}</td>
<i class="fa fa-fw fa-hourglass-end"></i> <td>{{ activity.durationTime|date('H:i') }}</td>
{{ activity.durationTime|date('H:i') }} <td>
</p> {% if activity.comment.comment is not empty %}
{% endif %} {{ activity.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
{% if activity.travelTime and t.travelTimeVisible %}
<p>
<i class="fa fa-fw fa-car"></i>
{{ activity.travelTime|date('H:i') }}
</p>
{% endif %}
</div>
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
<div class="mt-3">
<a class="btn btn-sm btn-outline-primary"
title="{{ 'Period number %number%'|trans({'%number%': activity.accompanyingPeriod.id}) }}"
href="{{ chill_path_add_return_path(
"chill_person_accompanying_course_index",
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
) }}"><i class="fa fa-random"></i>
</a>
</div>
{% endif %}
</div>
<div class="item-col">
<div class="float-button top">
<div class="box">
<div class="action">
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-sm btn-show "></a>
</li>
{% if no_action is not defined or no_action == false %}
{# TODO
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
#}
<li>
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-sm btn-update "></a>
</li>
{# TODO
{% endif %}
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
#}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
class="btn btn-sm btn-delete "></a>
</li>
{# TODO
{% endif %}
#}
{% endif %}
</ul>
</div>
<ul class="list-content">
{% if activity.user and t.userVisible %}
<li>
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
<b>{{ activity.user.usernameCanonical }}</b>
</li>
{% endif %}
<li>
<b>{{ activity.type.name | localize_translatable_string }}</b>
{% if activity.attendee is not null and t.attendeeVisible %}
{% if activity.attendee %}
{{ '→ ' ~ 'present'|trans|capitalize }}
{% else %}
{{ '→ ' ~ 'not present'|trans|capitalize }}
{% endif %}
{% endif %}
</li>
<li>
<b>{{ 'location'|trans ~ ': ' }}</b>
Domicile de l'usager
{# TODO {% if activity.location %}{{ activity.location }}{% endif %}
#}
</li>
{%- if t.reasonsVisible -%}
<li>
{%- if activity.reasons is not empty -%}
{% for r in activity.reasons %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialIssuesVisible %}
<li class="social-issues">
{%- if activity.socialIssues is not empty -%}
{% for r in activity.socialIssues %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialActionsVisible -%}
<li class="social-actions">
{%- if activity.socialActions is not empty -%}
{% for r in activity.socialActions %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
{% if activity.comment.comment is not empty
or activity.persons|length > 0
or activity.thirdParties|length > 0
or activity.users|length > 0
%}
<div class="item-row comment separator">
{% if activity.comment.comment is not empty %}
{{ activity.comment|chill_entity_render_box({
'disable_markdown': false,
'limit_lines': 3,
'metadata': false,
}) }}
{% endif %}
</div>
<div class="item-row details">
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
'context': context,
'with_display': 'bloc',
'entity': activity,
'badge_person': true
} %}
</div>
{% endif %} {% endif %}
{%- if activity.reasons is empty -%}
{{ 'No reason associated'|trans }}
</div> {%- else -%}
{% endfor %} {% for r in activity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}
</div> {%- endif -%}
</td>
<td>{{ activity.type.name | localize_translatable_string }}</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person.id }) }}" class="sc-button bt-show "></a>
</li>
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
<li>
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person.id }) }}" class="sc-button bt-update "></a>
</li>
{% endif %}
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person.id } ) }}" class="sc-button bt-delete "></a>
</li>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %} {% endif %}
</div> <ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create">
{{ 'Add a new activity' | trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,31 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
{% block content %}
{% set person_id = null %}
{% if person %}
{% set person_id = person.id %}
{% endif %}
{% set accompanying_course_id = null %}
{% if accompanyingCourse %}
{% set accompanying_course_id = accompanyingCourse.id %}
{% endif %}
<h1>{{ 'Activity list' |trans }}</h1>
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %}
<ul class="record_actions sticky-form-buttons">
<li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
{{ 'Add a new activity' | trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,47 +0,0 @@
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
{% block personcontent %}
{% set person_id = null %}
{% if person %}
{% set person_id = person.id %}
{% endif %}
{% set accompanying_course_id = null %}
{% if accompanyingCourse %}
{% set accompanying_course_id = accompanyingCourse.id %}
{% endif %}
<h1>{{ 'Activity list' |trans }}</h1>
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %}
<ul class="record_actions sticky-form-buttons">
<li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
class="btn btn-create disabled" tabindex="-1" role="button" aria-disabled="true">{{ 'Add a new activity' | trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,102 +1,50 @@
<h1>{{ "Activity creation"|trans ~ ' :' }}</h1> {#
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2> * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillPerson/layout.html.twig" %}
{{ form_start(form) }} {% set activeRouteKey = 'chill_activity_activity_new' %}
{{ form_errors(form) }}
{% block title 'Activity creation' |trans %}
{%- if form.emergency is defined -%} {% block personcontent %}
{{ form_row(form.emergency) }} <h2 class="chill-red">{{ "Activity creation"|trans }}</h1>
{% endif %}
{%- if form.sentReceived is defined -%} {{ form_start(form) }}
{{ form_row(form.sentReceived) }}
{% endif %}
{%- if form.user is defined -%}
{{ form_row(form.user) }} {{ form_row(form.user) }}
{% endif %}
{%- if form.scope is defined -%}
{{ form_row(form.scope) }} {{ form_row(form.scope) }}
{% endif %}
{%- if form.socialIssues is defined -%} <h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
{{ form_row(form.socialIssues) }}
{% endif %}
{%- if form.socialActions is defined -%}
{{ form_row(form.socialActions) }}
{% endif %}
<div id="social-issues-acc"></div>
{%- if form.reasons is defined -%}
{{ form_row(form.reasons) }}
{% endif %}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
{%- if form.persons is defined -%}
{{ form_widget(form.persons) }}
{% endif %}
{%- if form.thirdParties is defined -%}
{{ form_widget(form.thirdParties) }}
{% endif %}
{%- if form.users is defined -%}
{{ form_widget(form.users) }}
{% endif %}
<div id="add-persons"></div>
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
{%- if form.date is defined -%}
{{ form_row(form.date) }} {{ form_row(form.date) }}
{% endif %}
{# TODO .. location #}
{%- if form.durationTime is defined -%}
{{ form_row(form.durationTime) }} {{ form_row(form.durationTime) }}
{% endif %} {{ form_row(form.type) }}
{%- if form.travelTime is defined -%}
{{ form_row(form.travelTime) }}
{% endif %}
{%- if form.comment is defined -%}
{# TODO .. public and private #}
{{ form_row(form.comment) }}
{% endif %}
{%- if form.documents is defined -%}
{{ form_row(form.documents) }}
{% endif %}
{%- if form.attendee is defined -%}
{{ form_row(form.attendee) }} {{ form_row(form.attendee) }}
{% endif %} {{ form_row(form.reasons) }}
{{ form_row(form.comment) }}
{# TODO .. status #} <div class="grid-12 centered sticky-form-buttons">
<button class="sc-button green margin-10" type="submit"><i class="fa fa-save"></i> {{ 'Add a new activity'|trans }}</button>
</div>
{{ form_end(form) }}
{% endblock %}
<ul class="record_actions sticky-form-buttons"> {% block js %}
<li class="cancel"> <script type="text/javascript">
<a chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]', '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
class="btn btn-cancel" </script>
{%- if context == 'person' -%} {% endblock %}
href="{{ chill_return_path_or('chill_activity_activity_list', { 'person_id': person.id } )}}"
{%- else -%}
href="{{ chill_return_path_or('chill_activity_activity_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
{%- endif -%}
>
{{ 'Cancel'|trans|chill_return_path_label }}
</a>
</li>
<li>
<button class="btn btn-create" type="submit">
{{ 'Create'|trans }}
</button>
</li>
</ul>
{{ form_end(form) }}

View File

@@ -1,33 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_new' %}
{% block title 'Activity creation' |trans %}
{% block content %}
<div class="activity-new">
<div id="activity"></div> {# <=== vue component #}
{% include 'ChillActivityBundle:Activity:new.html.twig' with {'context': 'accompanyingCourse'} %}
</div>
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
});
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{% endblock %}

View File

@@ -1,31 +0,0 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_new' %}
{% block title 'Activity creation' |trans %}
{% block personcontent %}
<div class="activity-new">
<div id="activity"></div> {# <=== vue component #}
{% include 'ChillActivityBundle:Activity:new.html.twig' with {'context': 'person'} %}
</div>
{% endblock %}
{% block js %}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
});
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{% endblock %}

View File

@@ -1,35 +0,0 @@
<div class="new-activity-select-type">
<h2 class="chill-red">{{ "Activity creation"|trans }}</h2>
{# TODO: refaire l'html css des tuilles #}
{% for row in data %}
<h3>{{ row.activityTypeCategory.name|localize_translatable_string }}</h3>
<div class="activity-row">
{% for activityType in row.activityTypes %}
{% set person_id = null %}
{% if person %}
{% set person_id = person.id %}
{% endif %}
{% set accompanying_course_id = null %}
{% if accompanyingCourse %}
{% set accompanying_course_id = accompanyingCourse.id %}
{% endif %}
<a href="{{ path('chill_activity_activity_new', {
'person_id': person_id,
'activityType_id': activityType.id,
'accompanying_period_id': accompanying_course_id,
'activityData': activityData
}) }}">
<div class="bloc btn btn-primary btn-lg btn-block">
{{ activityType.name|localize_translatable_string }}
</div>
</a>
{% endfor %}
</div>
{% endfor %}
</div>

View File

@@ -1,9 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_new' %}
{% block title 'Activity creation'|trans %}
{% block content %}
{% include 'ChillActivityBundle:Activity:selectType.html.twig' %}
{% endblock %}

View File

@@ -1,9 +0,0 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_new' %}
{% block title 'Activity creation'|trans %}
{% block personcontent %}
{% include 'ChillActivityBundle:Activity:selectType.html.twig' %}
{% endblock %}

View File

@@ -1,147 +1,68 @@
{%- set t = entity.type -%} {% extends "@ChillPerson/layout.html.twig" %}
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
<h1> {% set activeRouteKey = 'chill_activity_activity_list' %}
{{ "Activity"|trans }}
{%- if t.emergencyVisible and entity.emergency -%}
<span class="badge bg-secondary">
{{- 'Emergency'|trans -}}
</span>
{%- endif -%}
</h1>
<dl class="chill_view_data"> {% block title 'Activity'|trans %}
<dt class="inline">{{ 'by'|trans|capitalize }}</dt> {% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
<dd>{{ entity.user }}</dd>
<dt class="inline">{{ 'Type'|trans }}</dt> {% block personcontent -%}
<dd>{{ entity.type.name | localize_translatable_string }}</dd> <h1 >{{ "Activity"|trans }}</h1>
{%- if entity.scope -%} <dl class="chill_view_data">
<dt class="inline">{{ 'User'|trans }}</dt>
<dd>{{ entity.user }}</dd>
<dt class="inline">{{ 'Scope'|trans }}</dt> <dt class="inline">{{ 'Scope'|trans }}</dt>
<dd><span class="scope">{{ entity.scope.name|localize_translatable_string }}</span></dd> <dd><span class="scope">{{ entity.scope.name|localize_translatable_string }}</span></dd>
{% endif %}
{% if t.socialIssuesVisible %} <h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
<dt class="inline">{{ 'Social issues'|trans }}</dt> <dt class="inline">{{ 'Person'|trans }}</dt>
<dd> <dd>{{ entity.person }}</dd>
{% if entity.socialIssues|length == 0 %}
<p class="chill-no-data-statement">{{ 'Any social issues'|trans }}</p>
{% else %}
{% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.socialActionsVisible %} <dt class="inline">{{ 'Date'|trans }}</dt>
<dt class="inline">{{ 'Social actions'|trans }}</dt> <dd>{{ entity.date|format_date('long') }}</dd>
<dd> <dt class="inline">{{ 'Duration Time'|trans }}</dt>
{% if entity.socialActions|length == 0 %} <dd>{{ entity.durationTime|date('H:i') }}</dd>
<p class="chill-no-data-statement">{{ 'Any social actions'|trans }}</p> <dt class="inline">{{ 'Type'|trans }}</dt>
{% else %} <dd>{{ entity.type.name | localize_translatable_string }}</dd>
{% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.reasonsVisible %} <dt class="inline">{{ 'Attendee'|trans }}</dt>
<dt class="inline">{{ 'Reasons'|trans }}</dt> <dd>{% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}</dd>
{%- if entity.reasons is empty -%}
<dd><span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span></dd>
{%- else -%}
<dd>{% for r in entity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}</dd>
{%- endif -%}
{% endif %}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2> <dt class="inline">{{ 'Reasons'|trans }}</dt>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc' } %} {%- if entity.reasons is empty -%}
<dd><span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span></dd>
{%- else -%}
<dd>{% for r in entity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}</dd>
{%- endif -%}
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2> <dt class="inline">{{ 'Comment'|trans }}</dt>
{%- if entity.comment is empty -%}
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd>
{%- else -%}
<dd>{{ entity.comment|chill_entity_render_box }}</dd>
{%- endif -%}
<dt class="inline">{{ 'Date'|trans }}</dt> </dl>
<dd>{{ entity.date|format_date('long') }}</dd>
{% if t.durationTimeVisible %} <ul class="record_actions">
<dt class="inline">{{ 'Duration Time'|trans }}</dt> <li class="cancel">
<dd>{% if entity.durationTime is not null %} <a class="sc-button bt-cancel" href="{{ path('chill_activity_activity_list', { 'person_id': person.id } ) }}">
{{ entity.durationTime|date('H:i') }} {{ 'Back to the list'|trans }}
{% else %} </a>
{{ 'None'|trans|capitalize }} </li>
{% endif %} <li>
</dd> <a class="sc-button bt-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person.id }) }}">
{% endif %} {{ 'Edit the activity'|trans }}
{% if t.travelTimeVisible %}
<dt class="inline">{{ 'Travel Time'|trans }}</dt>
<dd>{% if entity.travelTime is not null %}
{{ entity.travelTime|date('H:i') }}
{% else %}
{{ 'None'|trans|capitalize }}
{% endif %}
</dd>
{% endif %}
{% if t.commentVisible %}
<dt class="inline">{{ 'activity.comment'|trans }}</dt>
{%- if entity.comment.empty -%}
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd>
{%- else -%}
<dd>{{ entity.comment|chill_entity_render_box }}</dd>
{%- endif -%}
{% endif %}
{% if t.documentsVisible and entity.documents|length > 0 %}
<dt>{{ 'Documents'|trans }}</dt>
<dd>
<ul>
{% for d in entity.documents %}
<li>{{ m.download_button(d) }}</li>
{% endfor %}
</ul>
</dd>
{% endif %}
{% if t.attendeeVisible %}
<dt class="inline">{{ 'Attendee'|trans }}</dt>
<dd>{% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}</dd>
{% endif %}
</dl>
{% set person_id = null %}
{% if person %}
{% set person_id = person.id %}
{% endif %}
{% set accompanying_course_id = null %}
{% if accompanyingCourse %}
{% set accompanying_course_id = accompanyingCourse.id %}
{% endif %}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a class="btn btn-cancel" href="{{ path('chill_activity_activity_list', { 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}">
{{ 'Back to the list'|trans }}
</a> </a>
</li> </li>
<li> {% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
<a class="btn btn-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"> <li>
{{ 'Edit'|trans }} <a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person.id } ) }}" class="sc-button bt-delete">
</a> {{ 'Delete'|trans }}
</li> </a>
</li>
{% endif %}
</ul>
{# TODO {% endblock personcontent %}
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
#}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete">
{{ 'Delete'|trans }}
</a>
</li>
{#
{% endif %}
#}
</ul>

View File

@@ -1,15 +0,0 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title 'Show the activity'|trans %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
{% block content -%}
<div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
</div>
{% endblock content %}

View File

@@ -1,4 +0,0 @@
{{ dump(notification) }}
<a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId }) }}">Go to Activity</a>

View File

@@ -1,15 +0,0 @@
{% extends "@ChillPerson/Person/layout.html.twig" %}
{% set activeRouteKey = 'chill_activity_activity_list' %}
{% block title 'Show the activity'|trans %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
{% block personcontent -%}
<div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
</div>
{% endblock personcontent %}

View File

@@ -1,12 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %}
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
{% endblock %}
{% block layout_wvm_content %}
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
{% block content_form_actions_view %}{% endblock %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -1,44 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block admin_content %}
<h1>{{ 'ActivityPresence list'|trans }}</h1>
<table class="records_list">
<thead>
<tr>
<th>{{ 'Name'|trans }}</th>
<th>{{ 'Active'|trans }}</th>
<th>{{ 'Actions'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ entity.name|localize_translatable_string }}</td>
<td style="text-align:center;">
{%- if entity.active -%}
<i class="fa fa-check-square-o"></i>
{%- else -%}
<i class="fa fa-square-o"></i>
{%- endif -%}
</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('chill_crud_activity_presence_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul class="record_actions">
<li>
<a href="{{ path('chill_crud_activity_presence_new') }}" class="btn btn-create">
{{ 'Create a new activity presence'|trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,11 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %}
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
{% endblock %}
{% block layout_wvm_content %}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -26,10 +26,10 @@
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a> <a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
</li> </li>
<li> <li>
{{ form_row(edit_form.submit, { 'attr': { 'class' : 'btn btn-chill-orange' } } ) }} {{ form_row(edit_form.submit, { 'attr': { 'class' : 'sc-button orange' } } ) }}
</li> </li>
</ul> </ul>

View File

@@ -33,10 +33,10 @@
<td> <td>
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a> <a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="sc-button bt-show" title="{{ 'show'|trans }}"></a>
</li> </li>
<li> <li>
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a> <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
</li> </li>
</ul> </ul>
</td> </td>
@@ -47,7 +47,7 @@
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activityreason_new') }}" class="btn btn-new"> <a href="{{ path('chill_activity_activityreason_new') }}" class="sc-button bt-new">
{{ 'Create a new activity reason'|trans }} {{ 'Create a new activity reason'|trans }}
</a> </a>
</li> </li>

View File

@@ -26,10 +26,10 @@
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a> <a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
</li> </li>
<li> <li>
{{ form_row(form.submit, { 'attr': { 'class' : 'btn btn-new' } } ) }} {{ form_row(form.submit, { 'attr': { 'class' : 'sc-button bt-new' } } ) }}
</li> </li>
</ul> </ul>

View File

@@ -40,12 +40,12 @@
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel"> <a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }} {{ 'Back to the list'|trans }}
</a> </a>
</li> </li>
<li> <li>
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit"> <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
{{ 'Edit'|trans }} {{ 'Edit'|trans }}
</a> </a>
</li> </li>

View File

@@ -25,12 +25,12 @@
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel"> <a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }} {{ 'Back to the list'|trans }}
</a> </a>
</li> </li>
<li> <li>
{{ form_row(edit_form.submit, { 'attr': { 'class': 'btn btn-edit' } } ) }} {{ form_row(edit_form.submit, { 'attr': { 'class': 'sc-button bt-edit' } } ) }}
</li> </li>
</ul> </ul>

View File

@@ -34,10 +34,10 @@
<td> <td>
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a> <a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}" class="sc-button bt-show" title="{{ 'show'|trans }}"></a>
</li> </li>
<li> <li>
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a> <a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
</li> </li>
</ul> </ul>
</td> </td>
@@ -48,7 +48,7 @@
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activityreasoncategory_new') }}" class="btn btn-new"> <a href="{{ path('chill_activity_activityreasoncategory_new') }}" class="sc-button bt-new">
{{ 'Create a new activity category reason'|trans }} {{ 'Create a new activity category reason'|trans }}
</a> </a>
</li> </li>

View File

@@ -25,10 +25,10 @@
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a> <a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
</li> </li>
<li> <li>
{{ form_widget(form.submit, { 'attr': { 'class' : 'btn btn-new' } } ) }} {{ form_widget(form.submit, { 'attr': { 'class' : 'sc-button bt-new' } } ) }}
</li> </li>
</ul> </ul>
{{ form_end(form) }} {{ form_end(form) }}

View File

@@ -39,12 +39,12 @@
</table> </table>
<ul class="record_actions"> <ul class="record_actions">
<li class="cancel"> <li class="cancel">
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel"> <a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }} {{ 'Back to the list'|trans }}
</a> </a>
</li> </li>
<li> <li>
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="btn btn-edit"> <a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
{{ 'Edit'|trans }} {{ 'Edit'|trans }}
</a> </a>
</li> </li>

View File

@@ -1,12 +1,40 @@
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %} {% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %} {% block admin_content %}
{% include('@ChillMain/CRUD/_edit_title.html.twig') %} <h1>{{ 'ActivityType edit'|trans }}</h1>
{% endblock %}
{% block layout_wvm_content %} {{ form_start(edit_form) }}
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %} {{ form_row(edit_form.active) }}
{% block content_form_actions_view %}{% endblock %} {{ form_row(edit_form.name) }}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
<ul class="record_actions">
<li class="cancel">
<a href="{{ path('chill_activity_activitytype') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
{{ form_widget(edit_form.submit, { 'attr' : { 'class' : 'sc-button bt-update' } } ) }}
</li>
</ul>
{{ form_end(edit_form) }}
{% endblock %} {% endblock %}

View File

@@ -30,7 +30,7 @@
<tbody> <tbody>
{% for entity in entities %} {% for entity in entities %}
<tr> <tr>
<td>{{ entity.name|localize_translatable_string }}</td> <td><a href="{{ path('chill_activity_activitytype_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
<td style="text-align:center;"> <td style="text-align:center;">
{%- if entity.active -%} {%- if entity.active -%}
<i class="fa fa-check-square-o"></i> <i class="fa fa-check-square-o"></i>
@@ -41,7 +41,10 @@
<td> <td>
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_crud_activity_type_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a> <a href="{{ path('chill_activity_activitytype_show', { 'id': entity.id }) }}" class="sc-button bt-show" title="{{ 'show'|trans }}"></a>
</li>
<li>
<a href="{{ path('chill_activity_activitytype_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
</li> </li>
</ul> </ul>
</td> </td>
@@ -52,7 +55,7 @@
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_crud_activity_type_new') }}" class="btn btn-create"> <a href="{{ path('chill_activity_activitytype_new') }}" class="sc-button bt-create">
{{ 'Create a new activity type'|trans }} {{ 'Create a new activity type'|trans }}
</a> </a>
</li> </li>

View File

@@ -1,11 +1,38 @@
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %} {% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %} {% block admin_content %}
{% include('@ChillMain/CRUD/_new_title.html.twig') %} <h1>{{ 'ActivityType creation'|trans }}</h1>
{% endblock %}
{% block layout_wvm_content %} {{ form_start(form) }}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %} {{ form_row(form.active) }}
{% block content_form_actions_save_and_show %}{% endblock %} {{ form_row(form.name) }}
{% endembed %}
<ul class="record_actions">
<li class="cancel">
<a href="{{ path('chill_activity_activitytype') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
{{ form_widget(form.submit, { 'attr' : { 'class' : 'sc-button bt-new' } } ) }}
</li>
</ul>
{{ form_end(form) }}
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,42 @@
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block admin_content %}
<h1>{{ 'ActivityType'|trans }}</h1>
<table class="record_properties">
<tbody>
<tr>
<th>{{ 'Name'|trans }}</th>
<td>{{ entity.name|localize_translatable_string }}</td>
</tr>
</tbody>
</table>
<ul class="record_actions">
<li class="cancel">
<a href="{{ path('chill_activity_activitytype') }}" class="sc-button bt-cancel">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
<a href="{{ path('chill_activity_activitytype_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
{{ 'Edit'|trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,12 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %}
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
{% endblock %}
{% block layout_wvm_content %}
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
{% block content_form_actions_view %}{% endblock %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -1,44 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block admin_content %}
<h1>{{ 'ActivityTypeCategory list'|trans }}</h1>
<table class="records_list">
<thead>
<tr>
<th>{{ 'Name'|trans }}</th>
<th>{{ 'Active'|trans }}</th>
<th>{{ 'Actions'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ entity.name|localize_translatable_string }}</td>
<td style="text-align:center;">
{%- if entity.active -%}
<i class="fa fa-check-square-o"></i>
{%- else -%}
<i class="fa fa-square-o"></i>
{%- endif -%}
</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('chill_crud_activity_type_category_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul class="record_actions">
<li>
<a href="{{ path('chill_crud_activity_type_category_new') }}" class="btn btn-create">
{{ 'Create a new activity type category'|trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@@ -1,11 +0,0 @@
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
{% block title %}
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
{% endblock %}
{% block layout_wvm_content %}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -29,13 +29,13 @@
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activity_show', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="btn btn-view"> <a href="{{ path('chill_activity_activity_show', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="sc-button bt-view">
{{ 'Show the activity'|trans }} {{ 'Show the activity'|trans }}
</a> </a>
</li> </li>
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %} {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
<li> <li>
<a href="{{ path('chill_activity_activity_edit', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="btn btn-edit"> <a href="{{ path('chill_activity_activity_edit', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="sc-button bt-edit">
{{ 'Edit the activity'|trans }} {{ 'Edit the activity'|trans }}
</a> </a>
</li> </li>

View File

@@ -19,11 +19,6 @@
namespace Chill\ActivityBundle\Security\Authorization; namespace Chill\ActivityBundle\Security\Authorization;
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter; use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
@@ -33,10 +28,11 @@ use Chill\MainBundle\Entity\User;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Security;
/** /**
* Voter for Activity class *
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{ {
@@ -45,37 +41,30 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS'; const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS';
const UPDATE = 'CHILL_ACTIVITY_UPDATE'; const UPDATE = 'CHILL_ACTIVITY_UPDATE';
const DELETE = 'CHILL_ACTIVITY_DELETE'; const DELETE = 'CHILL_ACTIVITY_DELETE';
const FULL = 'CHILL_ACTIVITY_FULL';
private const ALL = [ /**
self::CREATE, *
self::SEE, * @var AuthorizationHelper
self::UPDATE, */
self::DELETE, protected $helper;
self::SEE_DETAILS,
self::FULL
];
protected VoterHelperInterface $voterHelper; public function __construct(AuthorizationHelper $helper)
{
protected Security $security; $this->helper = $helper;
public function __construct(
Security $security,
VoterHelperFactoryInterface $voterHelperFactory
) {
$this->security = $security;
$this->voterHelper = $voterHelperFactory->generate(self::class)
->addCheckFor(Person::class, [self::SEE, self::CREATE])
->addCheckFor(AccompanyingPeriod::class, [self::SEE, self::CREATE])
->addCheckFor(Activity::class, self::ALL)
->build();
} }
protected function supports($attribute, $subject) protected function supports($attribute, $subject)
{ {
return $this->voterHelper->supports($attribute, $subject); if ($subject instanceof Activity) {
return \in_array($attribute, $this->getAttributes());
} elseif ($subject instanceof Person) {
return $attribute === self::SEE
||
$attribute === self::CREATE;
} else {
return false;
}
} }
protected function voteOnAttribute($attribute, $subject, TokenInterface $token) protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
@@ -83,34 +72,32 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
if (!$token->getUser() instanceof User) { if (!$token->getUser() instanceof User) {
return false; return false;
} }
if ($subject instanceof Activity) { if ($subject instanceof Person) {
if ($subject->getPerson() instanceof Person) { $centers = $this->helper->getReachableCenters($token->getUser(), new Role($attribute));
// the context is person: we must have the right to see the person
if (!$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) { return \in_array($subject->getCenter(), $centers);
return false;
}
} elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) {
return false;
}
} else {
throw new \RuntimeException("could not determine context of activity");
}
} }
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token); /* @var $subject Activity */
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
}
private function getAttributes()
{
return [ self::CREATE, self::SEE, self::UPDATE, self::DELETE,
self::SEE_DETAILS ];
} }
public function getRoles() public function getRoles()
{ {
return self::ALL; return $this->getAttributes();
} }
public function getRolesWithoutScope() public function getRolesWithoutScope()
{ {
return []; return array();
} }

View File

@@ -35,37 +35,35 @@ class ActivityReasonRender extends AbstractChillEntityRender
* @var TranslatableStringHelper * @var TranslatableStringHelper
*/ */
protected $translatableStringHelper; protected $translatableStringHelper;
public function __construct(TranslatableStringHelper $translatableStringHelper) public function __construct(TranslatableStringHelper $translatableStringHelper)
{ {
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
public function renderBox($entity, array $options): string public function renderBox($entity, array $options): string
{ {
return return
$this->getDefaultOpeningBox('activity-reason'). $this->getDefaultOpeningBox('activity-reason').
'<span class="badge bg-chill-pink">'.
'<i class="fa fa-question-circle"></i>&nbsp;'. '<i class="fa fa-question-circle"></i>&nbsp;'.
'<span class="category">'. '<span class="activity-reason__category">'.
$this->translatableStringHelper->localize( $this->translatableStringHelper->localize(
$entity->getCategory()->getName() $entity->getCategory()->getName()
). ).
'</span>'. '</span>'.
'<span class="separator">&nbsp;>&nbsp;</span>'. '<span class="activity-reason__separator">&nbsp;>&nbsp;</span>'.
'<span class="reason">'. '<span class="activity-reason__reason">'.
$this->translatableStringHelper->localize( $this->translatableStringHelper->localize(
$entity->getName() $entity->getName()
). ).
'</span>'. '</span>'.
'</span>'.
$this->getDefaultClosingBox() $this->getDefaultClosingBox()
; ;
} }
/** /**
* *
* @param ActivityReason $entity * @param ActivityReason $entity
* @param array $options * @param array $options
* @return string * @return string
@@ -73,12 +71,12 @@ class ActivityReasonRender extends AbstractChillEntityRender
public function renderString($entity, array $options): string public function renderString($entity, array $options): string
{ {
$category = ''; $category = '';
if (null !== $entity->getCategory()) { if (null !== $entity->getCategory()) {
$category = $this->translatableStringHelper->localize( $category = $this->translatableStringHelper->localize(
$entity->getCategory()->getName()). ' > '; $entity->getCategory()->getName()). ' > ';
} }
return $category . return $category .
$this->translatableStringHelper->localize( $this->translatableStringHelper->localize(
$entity->getName() $entity->getName()

View File

@@ -1,11 +1,4 @@
// this file loads all assets from the Chill person bundle // this file loads all assets from the Chill person bundle
module.exports = function(encore, entries) module.exports = function(encore, entries) {
{ entries.push(__dirname + '/Resources/public/index.js');
entries.push(__dirname + '/Resources/public/chill/index.js');
encore.addAliases({
ChillActivityAssets: __dirname + '/Resources/public'
});
encore.addEntry('vue_activity', __dirname + '/Resources/public/vuejs/Activity/index.js');
}; };

View File

@@ -10,6 +10,10 @@ chill_activity_activityreasoncategory:
resource: "@ChillActivityBundle/config/routes/activityreasoncategory.yaml" resource: "@ChillActivityBundle/config/routes/activityreasoncategory.yaml"
prefix: / prefix: /
chill_activity_activitytype:
resource: "@ChillActivityBundle/config/routes/activitytype.yaml"
prefix: /
chill_admin_activity_index: chill_admin_activity_index:
path: /{_locale}/admin/activity path: /{_locale}/admin/activity
controller: Chill\ActivityBundle\Controller\AdminController::indexActivityAction controller: Chill\ActivityBundle\Controller\AdminController::indexActivityAction
@@ -28,30 +32,3 @@ chill_admin_activity_redirect_to_admin_index:
admin_activity: admin_activity:
order: 0 order: 0
label: Main admin menu label: Main admin menu
chill_activity_type_admin:
path: /{_locale}/admin/activity/type
controller: cscrud_activity_type_controller:index
options:
menus:
admin_activity:
order: 2020
label: 'Activity Types'
chill_activity_type_category_admin:
path: /{_locale}/admin/activity/type_category
controller: cscrud_activity_type_category_controller:index
options:
menus:
admin_activity:
order: 2999
label: 'Activity Types Categories'
chill_activity_presence_admin:
path: /{_locale}/admin/activity/presence
controller: cscrud_activity_presence_controller:index
options:
menus:
admin_activity:
order: 2021
label: 'Activity Presences'

View File

@@ -1,26 +1,30 @@
chill_activity_activity_list: chill_activity_activity_list:
path: /{_locale}/activity/ path: /{_locale}/person/{person_id}/activity/
controller: Chill\ActivityBundle\Controller\ActivityController::listAction controller: Chill\ActivityBundle\Controller\ActivityController::listAction
chill_activity_activity_show: chill_activity_activity_show:
path: /{_locale}/activity/{id}/show path: /{_locale}/person/{person_id}/activity/{id}/show
controller: Chill\ActivityBundle\Controller\ActivityController::showAction controller: Chill\ActivityBundle\Controller\ActivityController::showAction
chill_activity_activity_select_type:
path: /{_locale}/activity/select-type
controller: Chill\ActivityBundle\Controller\ActivityController::selectTypeAction
chill_activity_activity_new: chill_activity_activity_new:
path: /{_locale}/activity/new path: /{_locale}/person/{person_id}/activity/new
controller: Chill\ActivityBundle\Controller\ActivityController::newAction controller: Chill\ActivityBundle\Controller\ActivityController::newAction
methods: [POST, GET]
chill_activity_activity_create:
path: /{_locale}/person/{person_id}/activity/create
controller: Chill\ActivityBundle\Controller\ActivityController::createAction
methods: POST
chill_activity_activity_edit: chill_activity_activity_edit:
path: /{_locale}/activity/{id}/edit path: /{_locale}/person/{person_id}/activity/{id}/edit
controller: Chill\ActivityBundle\Controller\ActivityController::editAction controller: Chill\ActivityBundle\Controller\ActivityController::editAction
methods: [GET, POST, PUT]
chill_activity_activity_update:
path: /{_locale}/person/{person_id}/activity/{id}/update
controller: Chill\ActivityBundle\Controller\ActivityController::updateAction
methods: [POST, PUT]
chill_activity_activity_delete: chill_activity_activity_delete:
path: /{_locale}/activity/{id}/delete path: /{_locale}/person/{person_id}/activity/{id}/delete
controller: Chill\ActivityBundle\Controller\ActivityController::deleteAction controller: Chill\ActivityBundle\Controller\ActivityController::deleteAction
methods: [GET, POST, DELETE] methods: [GET, POST, DELETE]

View File

@@ -0,0 +1,35 @@
chill_activity_activitytype:
path: /{_locale}/admin/activitytype/
controller: Chill\ActivityBundle\Controller\ActivityTypeController::indexAction
options:
menus:
admin_activity:
order: 2020
label: "Activity Types"
chill_activity_activitytype_show:
path: /{_locale}/admin/activitytype/{id}/show
controller: Chill\ActivityBundle\Controller\ActivityTypeController::showAction
chill_activity_activitytype_new:
path: /{_locale}/admin/activitytype/new
controller: Chill\ActivityBundle\Controller\ActivityTypeController::newAction
chill_activity_activitytype_create:
path: /{_locale}/admin/activitytype/create
controller: Chill\ActivityBundle\Controller\ActivityTypeController::createAction
methods: POST
chill_activity_activitytype_edit:
path: /{_locale}/admin/activitytype/{id}/edit
controller: Chill\ActivityBundle\Controller\ActivityTypeController::editAction
chill_activity_activitytype_update:
path: /{_locale}/admin/activitytype/{id}/update
controller: Chill\ActivityBundle\Controller\ActivityTypeController::updateAction
methods: [POST, PUT]
chill_activity_activitytype_delete:
path: /{_locale}/admin/activitytype/{id}/delete
controller: Chill\ActivityBundle\Controller\ActivityTypeController::deleteAction
methods: [POST, DELETE]

Some files were not shown because too many files have changed in this diff Show More