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

This commit is contained in:
nobohan 2022-01-04 13:50:27 +01:00
commit f4c8d0b09a
611 changed files with 13079 additions and 4316 deletions

View File

@ -60,7 +60,7 @@ code_style:
- bin - bin
- tests/app/vendor/ - tests/app/vendor/
sa_tests: phpstan_tests:
stage: Tests stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4 image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script: script:
@ -71,6 +71,17 @@ sa_tests:
- bin - bin
- tests/app/vendor/ - tests/app/vendor/
psalm_tests:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
- bin/grumphp run --tasks=psalm
artifacts:
expire_in: 30 min
paths:
- bin
- tests/app/vendor/
unit_tests: unit_tests:
stage: Tests stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4 image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
@ -79,7 +90,7 @@ unit_tests:
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev - php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
- php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n - php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=test - php -d memory_limit=2G tests/app/bin/console cache:clear --env=test
- php -d memory_limit=3G bin/phpunit --colors=never - php -d memory_limit=4G bin/phpunit --colors=never
artifacts: artifacts:
expire_in: 30 min expire_in: 30 min
paths: paths:

View File

@ -11,11 +11,77 @@ and this project adheres to
## Unreleased ## Unreleased
<!-- write down unreleased development here --> <!-- write down unreleased development here -->
* [person search] fix bug when using birthdate after and birthdate before * AddAddress: optimize loading: wait for the user finish typing;
* [person search] increase pertinence when lastname begins with search pattern * UserPicker: fix bug with deprecated role
* docgen: add base context + tests
* docgen: add age for person
* [household menu] fix filiation order https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/265
* [AddAddress]: optimize loading: wait for the user finish typing;
* [UserPicker]: fix bug with deprecated role
* [docgen]: add base context + tests
* [docgen]: add age for person
* [task]: fix dropdown menu style + fix bug in singleTaskController (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/338)
* Household: fix bug when moving person on the same day (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/281)
* Household: show date validFrom and validTo when moving
* address reference: add index for refid
* [accompanyingCourse_work] fix styles conflicts + fix bug with remove goal (remove goals one at a time)
## Test releases ## Test releases
### test release 2021-12-14
* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262)
* [vendee/person] fix typo "situation professionelle" => "situation professionnelle"
* [main] add availableForUsers condition from locationType in the location API endpoint (champs-libres/departement-de-la-vendee/accent-suivi-developpement#248)
* [main] add the current location of the user as API point + add it in the activity location list (champs-libres/departement-de-la-vendee/accent-suivi-developpement#247)
* [activity] improve show/new/edit templates, fix SEE and SEE_DETAILS acl
* [badges] create specific badge for TMS, and make person/thirdparty badges clickable with on-the-fly modal in :
* concerned groups items (activity, calendar)
* accompanyingCourseWork lists
* accompanyingCourse lists
* [acompanyingCourse] add initial comment on Resume page
* [person] create button full width (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/330)
### test release 2021-12-11
* [main] add order field to civility
* [main] change address format in case the country is France, in Address render box and address normalizer
* [person] add validator for accompanying period with a test on social issues (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/76)
* [activity] fix visibility for location
* [origin] fix origin: use correctly the translatable strings
* /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');`
* [person] redirect bug fixed.
* [action] add an unrelated issue within action creation.
* [origin] fix origin: use correctly the translatable strings
* /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');`
* [main] change order of civilities in civility fixtures (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] set min attr in the minimum of children field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] add marital status date in person view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] show number of children + allow set number of children to null (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] show acceptSMS option (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [person] add death information in person render box in twig and vue render boxes (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191)
* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262)
* [vendee/person] fix typo "situation professionelle" => "situation professionnelle"
* [accompanyingcourse_work] Changes in layout/behavior of edit form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/321)
* [badge-entity] design coherency between pills badge-person and 3 kinds of badge-thirdparty
* [AddPersons] suggestions row are clickable, not only checkbox
### test release 2021-12-06
* [main] address: use search API end points for getting postal code and reference address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316)
* [main] address: in edit mode, select the encoded values in multiselect for address reference and city (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316)
* [person search] fix bug when using birthdate after and birthdate before
* [person search] increase pertinence when lastname begins with search pattern
* [activity/actions] Améliore la cohérence du design entre
* la page résumé d'un parcours (liste d'actions récentes et liste d'activités récentes)
* la page liste des actions
* la page liste des activités (contexte personne / contexte parcours)
* [household] field to edit wheter person is titulaire of household or not removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/322)
* [activity] create work if a work with same social action is not associated to the activity
* [visgraph] improve and fix bugs on vis-network relationship graph
* [bugfix] posting of birth- and deathdate through api fixed.
* [suggestions] improve suggestions lists
### Test release 2021-11-19 - bis ### Test release 2021-11-19 - bis
* [household] do not allow to create two addresses on the same date * [household] do not allow to create two addresses on the same date
@ -23,6 +89,7 @@ and this project adheres to
* [activity] layout for issues / actions * [activity] layout for issues / actions
* [activity][bugfix] in edit mode, the form will now load the social action list * [activity][bugfix] in edit mode, the form will now load the social action list
### Test release 2021-11-29 ### Test release 2021-11-29
* [person] suggest entities (person | thirdparty) when creating/editing the accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/119) * [person] suggest entities (person | thirdparty) when creating/editing the accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/119)
@ -50,6 +117,9 @@ and this project adheres to
* [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties * [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
* [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties * [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties
## Test releases
### Test release 2021-11-22 ### Test release 2021-11-22
* [activity] delete admin_user_show in twig template because this route is not defined and should be defined * [activity] delete admin_user_show in twig template because this route is not defined and should be defined
@ -164,7 +234,7 @@ and this project adheres to
* fast creation buttons * fast creation buttons
* add ordering for types * add ordering for types
* [AccompanyingCourse Resume page] badge-title for AccompanyingCourseWork and for Activities; * [AccompanyingCourse Resume page] dashboard for AccompanyingCourseWork and for Activities;
* Improve badges behaviour with small screens; * Improve badges behaviour with small screens;
* [ThirdParty]: * [ThirdParty]:

View File

@ -397,7 +397,6 @@ Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'an
<li> <li>
<span> <span>
item item
<a></a>
</span> </span>
</li> </li>
</ul> </ul>
@ -405,7 +404,8 @@ Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'an
Créer un titre enlevable (avec une croix rouge cliquable, l'ancre a est vide) Créer un titre enlevable (avec une croix rouge cliquable, l'ancre a est vide)
```html ```html
<div class="item-title"> <div class="item-title">
title <span>title</span>
<a></a>
</div> </div>
``` ```
Les classes `cols` ou `inline` peuvent être ajoutées à côté de `list-suggest` pour modifier la disposition de la liste.
Dans le dernier exemple, on met une classe `removable` sur le span, si on veut pouvoir enlever l'élément.

View File

@ -1,16 +1,17 @@
{ {
"name": "chill-project/chill-bundles", "name": "chill-project/chill-bundles",
"type": "library",
"description": "Most used bundles for chill-project", "description": "Most used bundles for chill-project",
"license": "AGPL-3.0-only",
"type": "library",
"keywords": [ "keywords": [
"chill", "chill",
"social worker" "social worker"
], ],
"license": "AGPL-3.0-only",
"require": { "require": {
"champs-libres/async-uploader-bundle": "dev-sf4", "php": "^7.4",
"champs-libres/wopi-bundle": "dev-master", "champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
"composer/package-versions-deprecated": "^1.10", "champs-libres/wopi-bundle": "dev-master#59b468503b9413f8d588ef9e626e7675560db3d8",
"champs-libres/wopi-lib": "dev-master#0e1da19bb6de820080b8651867a7e475be590060",
"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",
@ -21,34 +22,33 @@
"knplabs/knp-time-bundle": "^1.12", "knplabs/knp-time-bundle": "^1.12",
"league/csv": "^9.7.1", "league/csv": "^9.7.1",
"nyholm/psr7": "^1.4", "nyholm/psr7": "^1.4",
"ocramius/package-versions": "^1.10",
"phpoffice/phpspreadsheet": "^1.16", "phpoffice/phpspreadsheet": "^1.16",
"ramsey/uuid-doctrine": "^1.7", "ramsey/uuid-doctrine": "^1.7",
"sensio/framework-extra-bundle": "^5.5", "sensio/framework-extra-bundle": "^5.5",
"symfony/asset": "4.*", "spomky-labs/base64url": "^2.0",
"symfony/browser-kit": "^5.2", "symfony/asset": "^4.4",
"symfony/css-selector": "^5.2", "symfony/browser-kit": "^4.4",
"symfony/expression-language": "4.*", "symfony/css-selector": "^4.4",
"symfony/form": "4.*", "symfony/expression-language": "^4.4",
"symfony/intl": "4.*", "symfony/form": "^4.4",
"symfony/mime": "^4 || ^5", "symfony/intl": "^4.4",
"symfony/mime": "^4.4",
"symfony/monolog-bundle": "^3.5", "symfony/monolog-bundle": "^3.5",
"symfony/security-bundle": "4.*", "symfony/security-bundle": "^4.4",
"symfony/serializer": "^5.2", "symfony/serializer": "^5.3",
"symfony/swiftmailer-bundle": "^3.5", "symfony/swiftmailer-bundle": "^3.5",
"symfony/templating": "4.*", "symfony/templating": "^4.4",
"symfony/translation": "4.*", "symfony/translation": "^4.4",
"symfony/twig-bundle": "^4.4", "symfony/twig-bundle": "^4.4",
"symfony/validator": "4.*", "symfony/validator": "^4.4",
"symfony/webpack-encore-bundle": "^1.11", "symfony/webpack-encore-bundle": "^1.11",
"symfony/workflow": "4.*", "symfony/workflow": "^4.4",
"symfony/yaml": "4.*", "symfony/yaml": "^4.4",
"twig/extra-bundle": "^2.12 || ^3.0", "twig/extra-bundle": "^3.0",
"twig/intl-extra": "^3.0", "twig/intl-extra": "^3.0",
"twig/markdown-extra": "^3.3", "twig/markdown-extra": "^3.3",
"twig/twig": "^2.12 || ^3.0" "twig/twig": "^3.0"
},
"conflict": {
"symfony/symfony": "*"
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3", "doctrine/doctrine-fixtures-bundle": "^3.3",
@ -56,18 +56,17 @@
"fakerphp/faker": "^1.13", "fakerphp/faker": "^1.13",
"nelmio/alice": "^3.8", "nelmio/alice": "^3.8",
"phpstan/phpstan-strict-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^7.0", "phpunit/phpunit": ">= 7.5",
"symfony/debug-bundle": "^5.1", "symfony/debug-bundle": "^5.1",
"symfony/dotenv": "^5.1", "symfony/dotenv": "^4.4",
"symfony/maker-bundle": "^1.20", "symfony/maker-bundle": "^1.20",
"symfony/phpunit-bridge": "^5.2", "symfony/phpunit-bridge": "^4.4",
"symfony/stopwatch": "^5.1", "symfony/stopwatch": "^4.4",
"symfony/var-dumper": "4.*", "symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^5.0" "symfony/web-profiler-bundle": "^4.4"
}, },
"config": { "conflict": {
"bin-dir": "bin", "symfony/symfony": "*"
"vendor-dir": "tests/app/vendor"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -94,8 +93,19 @@
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests" "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
} }
}, },
"minimum-stability": "dev", "config": {
"prefer-stable": true, "allow-plugins": {
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true,
"ergebnis/composer-normalize": true,
"phpro/grumphp": true,
"ocramius/package-versions": true
},
"bin-dir": "bin",
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "tests/app/vendor"
},
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
"cache:clear": "symfony-cmd", "cache:clear": "symfony-cmd",

View File

@ -91,7 +91,9 @@ class CountPerson implements ExportInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{ {
// we gather all center the user choose. // we gather all center the user choose.
$centers = array_map(static function ($el) { return $el['center']; }, $acl); $centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder(); $qb = $this->entityManager->createQueryBuilder();

View File

@ -11,53 +11,53 @@ declare(strict_types=1);
namespace Chill\MainBundle\DependencyInjection; namespace Chill\MainBundle\DependencyInjection;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait; use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
/** /**
* Configure the main bundle. * Configure the main bundle.
*/ */
class ChillMainConfiguration implements ConfigurationInterface class ChillMainConfiguration implements ConfigurationInterface
{ {
use AddWidgetConfigurationTrait; use AddWidgetConfigurationTrait;
/** /**
* @var ContainerBuilder * @var ContainerBuilder
*/ */
private $containerBuilder; private $containerBuilder;
public function __construct( public function __construct(
array $widgetFactories, array $widgetFactories,
ContainerBuilder $containerBuilder ContainerBuilder $containerBuilder
) { ) {
// we register here widget factories (see below) // we register here widget factories (see below)
$this->setWidgetFactories($widgetFactories); $this->setWidgetFactories($widgetFactories);
// we will need the container builder later... // we will need the container builder later...
$this->containerBuilder = $containerBuilder; $this->containerBuilder = $containerBuilder;
} }
public function getConfigTreeBuilder() public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('chill_main'); $rootNode = $treeBuilder->root('chill_main');
$rootNode $rootNode
->children() ->children()
// ... // ...
->arrayNode('widgets') ->arrayNode('widgets')
->canBeDisabled() ->canBeDisabled()
->children() ->children()
// we declare here all configuration for homepage place // we declare here all configuration for homepage place
->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder)) ->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
->end() // end of widgets/children ->end() // end of widgets/children
->end() // end of widgets ->end() // end of widgets
->end() // end of root/children ->end() // end of root/children
->end() // end of root ->end() // end of root
; ;
return $treeBuilder; return $treeBuilder;
} }
} }

View File

@ -12,3 +12,28 @@ parameters:
tasks.phpcsfixer.allow_risky: true tasks.phpcsfixer.allow_risky: true
tasks.phpcsfixer.diff: true tasks.phpcsfixer.diff: true
tasks.phpstan.level: 1 tasks.phpstan.level: 1
tasks.phpstan.blocking: true
tasks.phpstan.ignore_patterns:
- "/.github/"
- "/.idea/"
- "/build/"
- "/benchmarks/"
- "/docs/"
- "/node_modules/"
- "/resource/"
- "/spec/"
- "/var/"
- "/vendor/"
# Psalm
tasks.psalm.blocking: true
tasks.psalm.ignore_patterns:
- "/.github/"
- "/.idea/"
- "/build/"
- "/benchmarks/"
- "/node_modules/"
- "/resource/"
- "/spec/"
- "/var/"
- "/vendor/"

View File

@ -10,16 +10,6 @@ parameters:
count: 1 count: 1
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
-
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
count: 1
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorController.php
-
message: "#^Instantiated class PhpOffice\\\\PhpWord\\\\TemplateProcessor not found\\.$#"
count: 1
path: src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php
- -
message: "#^Variable \\$participation might not be defined\\.$#" message: "#^Variable \\$participation might not be defined\\.$#"
count: 3 count: 3

View File

@ -417,15 +417,6 @@ parameters:
count: 1 count: 1
path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
-
message:
"""
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 3
path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
- -
message: message:
""" """
@ -435,15 +426,6 @@ parameters:
count: 1 count: 1
path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
-
message:
"""
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php
- -
message: message:
""" """
@ -525,24 +507,6 @@ parameters:
count: 1 count: 1
path: src/Bundle/ChillEventBundle/Search/EventSearch.php path: src/Bundle/ChillEventBundle/Search/EventSearch.php
-
message:
"""
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 2
path: src/Bundle/ChillEventBundle/Search/EventSearch.php
-
message:
"""
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillEventBundle/Timeline/TimelineEventProvider.php
- -
message: message:
""" """
@ -1311,16 +1275,6 @@ parameters:
count: 1 count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
-
message:
"""
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
"""
count: 1
path: src/Bundle/ChillPersonBundle/Search/SimilarPersonMatcher.php
- -
message: message:
""" """

View File

@ -2,10 +2,11 @@
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html --> <!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false" backupGlobals="false"
colors="true" colors="true"
bootstrap="tests/app/tests/bootstrap.php" bootstrap="tests/app/tests/bootstrap.php"
stopOnFailure="true"
> >
<php> <php>
<ini name="error_reporting" value="-1" /> <ini name="error_reporting" value="-1" />

2006
psalm-baseline.xml Normal file

File diff suppressed because it is too large Load Diff

16
psalm.xml Normal file
View File

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

View File

@ -39,6 +39,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\SerializerInterface;
use function array_key_exists; use function array_key_exists;
final class ActivityController extends AbstractController final class ActivityController extends AbstractController
@ -307,8 +308,10 @@ final class ActivityController extends AbstractController
$activityData = $request->query->get('activityData'); $activityData = $request->query->get('activityData');
} }
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType if (
|| !$activityType->isActive()) { !$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType
|| !$activityType->isActive()
) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod); $params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) { if (null !== $activityData) {

View File

@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\ActivityReasonCategory; use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Chill\ActivityBundle\Form\ActivityReasonCategoryType; use Chill\ActivityBundle\Form\ActivityReasonCategoryType;
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\Request; use Symfony\Component\HttpFoundation\Request;

View File

@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\ActivityReason; use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType; use Chill\ActivityBundle\Form\ActivityReasonType;
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\Request; use Symfony\Component\HttpFoundation\Request;

View File

@ -19,6 +19,7 @@ use Chill\MainBundle\Entity\RoleScope;
use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use function in_array; use function in_array;
/** /**

View File

@ -41,6 +41,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
$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'); $loader->load('services/accompanyingPeriodConsistency.yaml');
$loader->load('services/doctrine.entitylistener.yaml');
} }
public function prepend(ContainerBuilder $container) public function prepend(ContainerBuilder $container)

View File

@ -13,6 +13,7 @@ namespace Chill\ActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use function is_int; use function is_int;
/** /**

View File

@ -47,7 +47,8 @@ use Symfony\Component\Serializer\Annotation\SerializedName;
* }) * })
* @ActivityValidator\ActivityValidity * @ActivityValidator\ActivityValidity
* *
* @UserCircleConsistency( * TODO see if necessary
* UserCircleConsistency(
* "CHILL_ACTIVITY_SEE_DETAILS", * "CHILL_ACTIVITY_SEE_DETAILS",
* getUserFunction="getUser", * getUserFunction="getUser",
* path="scope") * path="scope")

View File

@ -163,16 +163,6 @@ class ActivityType
*/ */
private int $personVisible = self::FIELD_REQUIRED; private int $personVisible = self::FIELD_REQUIRED;
/**
* @ORM\Column(type="string", nullable=false, options={"default": ""})
*/
private string $placeLabel = '';
/**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
*/
private int $placeVisible = self::FIELD_OPTIONAL;
/** /**
* @ORM\Column(type="string", nullable=false, options={"default": ""}) * @ORM\Column(type="string", nullable=false, options={"default": ""})
*/ */
@ -406,16 +396,6 @@ class ActivityType
return $this->personVisible; return $this->personVisible;
} }
public function getPlaceLabel(): string
{
return $this->placeLabel;
}
public function getPlaceVisible(): int
{
return $this->placeVisible;
}
public function getReasonsLabel(): string public function getReasonsLabel(): string
{ {
return $this->reasonsLabel; return $this->reasonsLabel;
@ -688,20 +668,6 @@ class ActivityType
return $this; return $this;
} }
public function setPlaceLabel(string $placeLabel): self
{
$this->placeLabel = $placeLabel;
return $this;
}
public function setPlaceVisible(int $placeVisible): self
{
$this->placeVisible = $placeVisible;
return $this;
}
public function setReasonsLabel(string $reasonsLabel): self public function setReasonsLabel(string $reasonsLabel): self
{ {
$this->reasonsLabel = $reasonsLabel; $this->reasonsLabel = $reasonsLabel;

View File

@ -0,0 +1,77 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ActivityBundle\EntityListener;
use Chill\ActivityBundle\Entity\Activity;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use function in_array;
class ActivityEntityListener
{
private EntityManagerInterface $em;
private AccompanyingPeriodWorkRepository $workRepository;
public function __construct(EntityManagerInterface $em, AccompanyingPeriodWorkRepository $workRepository)
{
$this->em = $em;
$this->workRepository = $workRepository;
}
public function persistActionToCourse(Activity $activity)
{
if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
$period = $activity->getAccompanyingPeriod();
$accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period);
$periodActions = [];
$now = new DateTimeImmutable();
foreach ($accompanyingCourseWorks as $key => $work) {
// take only the actions which are still opened
if ($work->getEndDate() === null || $work->getEndDate() > ($activity->getDate() ?? $now)) {
$periodActions[$key] = spl_object_hash($work->getSocialAction());
}
}
$associatedPersons = $activity->getPersonsAssociated();
$associatedThirdparties = $activity->getThirdParties();
foreach ($activity->getSocialActions() as $action) {
if (in_array(spl_object_hash($action), $periodActions, true)) {
continue;
}
$newAction = new AccompanyingPeriodWork();
$newAction->setSocialAction($action);
$period->addWork($newAction);
$date = DateTimeImmutable::createFromMutable($activity->getDate());
$newAction->setStartDate($date);
foreach ($associatedPersons as $person) {
$newAction->addPerson($person);
}
foreach ($associatedThirdparties as $thirdparty) {
$newAction->setHandlingThierparty($thirdparty);
}
$this->em->persist($newAction);
$this->em->flush();
}
}
}
}

View File

@ -25,6 +25,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists; use function array_key_exists;
use function count; use function count;

View File

@ -27,6 +27,7 @@ use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists; use function array_key_exists;
use function count; use function count;
use function in_array; use function in_array;
@ -189,7 +190,9 @@ class ListActivity implements ListInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{ {
$centers = array_map(static function ($el) { return $el['center']; }, $acl); $centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
// throw an error if any fields are present // throw an error if any fields are present
if (!array_key_exists('fields', $data)) { if (!array_key_exists('fields', $data)) {

View File

@ -25,6 +25,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists; use function array_key_exists;
use function count; use function count;

View File

@ -24,6 +24,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count; use function count;
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface

View File

@ -31,6 +31,7 @@ use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count; use function count;
class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface

View File

@ -48,6 +48,7 @@ use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use function in_array; use function in_array;
class ActivityType extends AbstractType class ActivityType extends AbstractType
@ -260,6 +261,10 @@ class ActivityType extends AbstractType
return implode(',', $personIds); return implode(',', $personIds);
}, },
function (?string $personsAsString): array { function (?string $personsAsString): array {
if (null === $personsAsString) {
return [];
}
return array_map( return array_map(
fn (string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]), fn (string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]),
explode(',', $personsAsString) explode(',', $personsAsString)
@ -282,6 +287,10 @@ class ActivityType extends AbstractType
return implode(',', $thirdpartyIds); return implode(',', $thirdpartyIds);
}, },
function (?string $thirdpartyAsString): array { function (?string $thirdpartyAsString): array {
if (null === $thirdpartyAsString) {
return [];
}
return array_map( return array_map(
fn (string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]), fn (string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]),
explode(',', $thirdpartyAsString) explode(',', $thirdpartyAsString)
@ -315,6 +324,10 @@ class ActivityType extends AbstractType
return implode(',', $userIds); return implode(',', $userIds);
}, },
function (?string $usersAsString): array { function (?string $usersAsString): array {
if (null === $usersAsString) {
return [];
}
return array_map( return array_map(
fn (string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]), fn (string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]),
explode(',', $usersAsString) explode(',', $usersAsString)
@ -332,7 +345,7 @@ class ActivityType extends AbstractType
return ''; return '';
} }
return $location->getId(); return (string) $location->getId();
}, },
function (?string $id): ?Location { function (?string $id): ?Location {
return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]); return $this->om->getRepository(Location::class)->findOneBy(['id' => (int) $id]);
@ -379,7 +392,7 @@ class ActivityType extends AbstractType
$timezoneUTC = new DateTimeZone('GMT'); $timezoneUTC = new DateTimeZone('GMT');
/** @var DateTime $data */ /** @var DateTime $data */
$data = $formEvent->getData() === null ? $data = $formEvent->getData() === null ?
DateTime::createFromFormat('U', 300) : DateTime::createFromFormat('U', '300') :
$formEvent->getData(); $formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data); $seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC); $data->setTimeZone($timezoneUTC);

View File

@ -55,7 +55,7 @@ class ActivityTypeType extends AbstractType
]); ]);
$fields = [ $fields = [
'persons', 'user', 'date', 'place', 'persons', 'persons', 'user', 'date', 'location', 'persons',
'thirdParties', 'durationTime', 'travelTime', 'attendee', 'thirdParties', 'durationTime', 'travelTime', 'attendee',
'reasons', 'comment', 'sentReceived', 'documents', 'reasons', 'comment', 'sentReceived', 'documents',
'emergency', 'socialIssues', 'socialActions', 'users', 'emergency', 'socialIssues', 'socialActions', 'users',

View File

@ -36,8 +36,10 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
{ {
$period = $parameters['accompanyingCourse']; $period = $parameters['accompanyingCourse'];
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep() if (
&& $this->security->isGranted(ActivityVoter::SEE, $period)) { AccompanyingPeriod::STEP_DRAFT !== $period->getStep()
&& $this->security->isGranted(ActivityVoter::SEE, $period)
) {
$menu->addChild($this->translator->trans('Activity'), [ $menu->addChild($this->translator->trans('Activity'), [
'route' => 'chill_activity_activity_list', 'route' => 'chill_activity_activity_list',
'routeParameters' => [ 'routeParameters' => [

View File

@ -14,6 +14,7 @@ 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\Security; use Symfony\Component\Security\Core\Security;
use function in_array; use function in_array;
final class AdminMenuBuilder implements LocalMenuBuilderInterface final class AdminMenuBuilder implements LocalMenuBuilderInterface

View File

@ -22,6 +22,7 @@ use Doctrine\ORM\EntityManagerInterface;
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 Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use function count; use function count;
use function in_array; use function in_array;
@ -167,7 +168,9 @@ 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(
static function (Scope $scope) { return $scope->getId(); }, static function (Scope $scope) {
return $scope->getId();
},
$reachableScopes $reachableScopes
); );

View File

@ -31,6 +31,8 @@ class ActivityRepository extends ServiceEntityRepository
} }
/** /**
* @deprecated use @see{ActivityACLAwareRepositoryInterface::findByAccompanyingPeriod}
*
* @return Activity[] * @return Activity[]
*/ */
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array

View File

@ -24,14 +24,16 @@ div.new-activity-select-type {
} }
//// ACTIVITY LIST PAGE //// ACTIVITY LIST PAGE
// precise badge-title specific details // precise dashboard specific details
p.date-label {
display: inline-block;
margin: 0 0.5em 0 0;
font-weight: 700;
font-size: 18pt;
}
div.dashboard,
h2.badge-title { h2.badge-title {
div.duration {
font-size: smaller;
padding-left: 1em;
margin-top: 1em;
}
ul.list-content { ul.list-content {
font-size: 70%; font-size: 70%;
list-style-type: none; list-style-type: none;
@ -39,16 +41,13 @@ h2.badge-title {
margin: 0; margin: 0;
li { li {
margin-bottom: 0.2em; margin-bottom: 0.2em;
// exception: change bg color for action badges above badge-title // exception: change bg color for action badges above dashboard
.bg-light { .bg-light {
background-color: $chill-light-gray !important; background-color: $chill-light-gray !important;
} }
} }
} }
} }
div.main {
padding: 1em;
}
//// ACTIVITY SHOW AND FORM PAGES //// ACTIVITY SHOW AND FORM PAGES
// Exceptions for flex-bloc in concerned-groups // Exceptions for flex-bloc in concerned-groups

View File

@ -17,6 +17,14 @@ const getLocations = () => fetchResults('/api/1.0/main/location.json');
const getLocationTypes = () => fetchResults('/api/1.0/main/location-type.json'); const getLocationTypes = () => fetchResults('/api/1.0/main/location-type.json');
const getUserCurrentLocation =
() => fetch('/api/1.0/main/user-current-location.json')
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
/* /*
* Load Location Type by defaultFor * Load Location Type by defaultFor
* @param {string} entity - can be "person" or "thirdparty" * @param {string} entity - can be "person" or "thirdparty"
@ -48,5 +56,6 @@ export {
getLocations, getLocations,
getLocationTypes, getLocationTypes,
getLocationTypeByDefaultFor, getLocationTypeByDefaultFor,
postLocation postLocation,
getUserCurrentLocation
}; };

View File

@ -11,7 +11,7 @@
</persons-bloc> </persons-bloc>
</div> </div>
<div v-if="getContext === 'accompanyingCourse' && suggestedEntities.length > 0"> <div v-if="getContext === 'accompanyingCourse' && suggestedEntities.length > 0">
<ul class="list-suggest add-items"> <ul class="list-suggest add-items inline">
<li v-for="p in suggestedEntities" @click="addSuggestedEntity(p)"> <li v-for="p in suggestedEntities" @click="addSuggestedEntity(p)">
<span>{{ p.text }}</span> <span>{{ p.text }}</span>
</li> </li>

View File

@ -1,8 +1,7 @@
<template> <template>
<li> <li>
<span :title="person.text"> <span :title="person.text">
<span class="chill_denomination">{{ textCutted }}</span> <span class="chill_denomination" @click.prevent="$emit('remove', person)">{{ textCutted }}</span>
<a @click.prevent="$emit('remove', person)"></a>
</span> </span>
</li> </li>
</template> </template>

View File

@ -15,7 +15,7 @@
:searchable="true" :searchable="true"
:placeholder="$t('activity.choose_location')" :placeholder="$t('activity.choose_location')"
:custom-label="customLabel" :custom-label="customLabel"
:options="locations" :options="availableLocations"
group-values="locations" group-values="locations"
group-label="locationGroup" group-label="locationGroup"
v-model="location" v-model="location"
@ -32,7 +32,7 @@
import { mapState, mapGetters } from "vuex"; import { mapState, mapGetters } from "vuex";
import VueMultiselect from "vue-multiselect"; import VueMultiselect from "vue-multiselect";
import NewLocation from "./Location/NewLocation.vue"; import NewLocation from "./Location/NewLocation.vue";
import { getLocations, getLocationTypeByDefaultFor } from "../api.js"; import { getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation } from "../api.js";
export default { export default {
name: "Location", name: "Location",
@ -40,13 +40,8 @@ export default {
NewLocation, NewLocation,
VueMultiselect, VueMultiselect,
}, },
data() {
return {
locations: [],
};
},
computed: { computed: {
...mapState(["activity"]), ...mapState(["activity", "availableLocations"]),
...mapGetters(["suggestedEntities"]), ...mapGetters(["suggestedEntities"]),
location: { location: {
get() { get() {
@ -57,53 +52,6 @@ export default {
}, },
}, },
}, },
mounted() {
getLocations().then(
(results) => {
getLocationTypeByDefaultFor('person').then(
(personLocationType) => {
if (personLocationType) {
const personLocation = this.makeAccompanyingPeriodLocation(personLocationType);
const concernedPersonsLocation =
this.makeConcernedPersonsLocation(personLocationType);
getLocationTypeByDefaultFor('thirdparty').then(
thirdpartyLocationType => {
const concernedThirdPartiesLocation =
this.makeConcernedThirdPartiesLocation(thirdpartyLocationType);
this.locations = [
{
locationGroup: 'Localisation du parcours',
locations: [personLocation]
},
{
locationGroup: 'Parties concernées',
locations: [...concernedPersonsLocation, ...concernedThirdPartiesLocation]
},
{
locationGroup: 'Autres localisations',
locations: results
}
];
}
)
} else {
this.locations = [
{
locationGroup: 'Localisations',
locations: response.results
}
];
}
if (window.default_location_id) {
let location = this.locations.filter(
(l) => l.id === window.default_location_id
);
this.$store.dispatch("updateLocation", location);
}
}
)
})
},
methods: { methods: {
labelAccompanyingCourseLocation(value) { labelAccompanyingCourseLocation(value) {
return `${value.address.text} (${value.locationType.title.fr})` return `${value.address.text} (${value.locationType.title.fr})`
@ -117,58 +65,6 @@ export default {
: value.locationType.title.fr : value.locationType.title.fr
: ''; : '';
}, },
makeConcernedPersonsLocation(locationType) {
let locations = [];
this.suggestedEntities.forEach(
(e) => {
if (e.type === 'person' && e.current_household_address !== null){
locations.push({
type: 'location',
id: -this.suggestedEntities.indexOf(e)*10,
onthefly: true,
name: e.text,
address: {
id: e.current_household_address.address_id,
},
locationType: locationType
});
}
}
)
return locations;
},
makeConcernedThirdPartiesLocation(locationType) {
let locations = [];
this.suggestedEntities.forEach(
(e) => {
if (e.type === 'thirdparty' && e.address !== null){
locations.push({
type: 'location',
id: -this.suggestedEntities.indexOf(e)*10,
onthefly: true,
name: e.text,
address: { id: e.address.address_id },
locationType: locationType
});
}
}
)
return locations;
},
makeAccompanyingPeriodLocation(locationType) {
const accPeriodLocation = this.activity.accompanyingPeriod.location;
return {
type: 'location',
id: -1,
onthefly: true,
name: '__AccompanyingCourseLocation__',
address: {
id: accPeriodLocation.address_id,
text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}`
},
locationType: locationType
}
}
}, },
}; };
</script> </script>

View File

@ -1,22 +1,23 @@
import 'es6-promise/auto'; import 'es6-promise/auto';
import { createStore } from 'vuex'; import { createStore } from 'vuex';
import { postLocation } from './api'; import { postLocation } from './api';
import prepareLocations from './store.locations.js';
const debug = process.env.NODE_ENV !== 'production'; const debug = process.env.NODE_ENV !== 'production';
//console.log('window.activity', window.activity); //console.log('window.activity', window.activity);
const addIdToValue = (string, id) => { const addIdToValue = (string, id) => {
let array = string ? string.split(',') : []; let array = string ? string.split(',') : [];
array.push(id.toString()); array.push(id.toString());
let str = array.join(); let str = array.join();
return str; return str;
}; };
const removeIdFromValue = (string, id) => { const removeIdFromValue = (string, id) => {
let array = string.split(','); let array = string.split(',');
array = array.filter(el => el !== id.toString()); array = array.filter(el => el !== id.toString());
let str = array.join(); let str = array.join();
return str; return str;
}; };
const store = createStore({ const store = createStore({
@ -25,6 +26,7 @@ const store = createStore({
activity: window.activity, activity: window.activity,
socialIssuesOther: [], socialIssuesOther: [],
socialActionsList: [], socialActionsList: [],
availableLocations: [],
}, },
getters: { getters: {
suggestedEntities(state) { suggestedEntities(state) {
@ -50,9 +52,9 @@ const store = createStore({
return state.activity.activityType.personsVisible === 0 return state.activity.activityType.personsVisible === 0
? [] ? []
: state.activity.accompanyingPeriod.participations : state.activity.accompanyingPeriod.participations
.filter((p) => p.endDate === null) .filter((p) => p.endDate === null)
.map((p) => p.person) .map((p) => p.person)
.filter((p) => !existingPersonIds.includes(p.id)); .filter((p) => !existingPersonIds.includes(p.id));
}, },
suggestedRequestor(state) { suggestedRequestor(state) {
if (state.activity.accompanyingPeriod.requestor === null) { if (state.activity.accompanyingPeriod.requestor === null) {
@ -78,8 +80,8 @@ const store = createStore({
return state.activity.activityType.usersVisible === 0 return state.activity.activityType.usersVisible === 0
? [] ? []
: [state.activity.accompanyingPeriod.user].filter( : [state.activity.accompanyingPeriod.user].filter(
(u) => u !== null && !existingUserIds.includes(u.id) (u) => u !== null && !existingUserIds.includes(u.id)
); );
}, },
suggestedResources(state) { suggestedResources(state) {
const resources = state.activity.accompanyingPeriod.resources; const resources = state.activity.accompanyingPeriod.resources;
@ -200,6 +202,9 @@ const store = createStore({
console.log("### mutation: updateLocation", value); console.log("### mutation: updateLocation", value);
state.activity.location = value; state.activity.location = value;
}, },
addAvailableLocationGroup(state, group) {
state.availableLocations.push(group);
}
}, },
actions: { actions: {
addIssueSelected({ commit }, issue) { addIssueSelected({ commit }, issue) {
@ -335,4 +340,6 @@ const store = createStore({
}, },
}); });
prepareLocations(store);
export default store; export default store;

View File

@ -0,0 +1,123 @@
import {getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation} from "./api";
const makeConcernedPersonsLocation = (locationType, store) => {
let locations = [];
store.getters.suggestedEntities.forEach(
(e) => {
if (e.type === 'person' && e.current_household_address !== null){
locations.push({
type: 'location',
id: -store.getters.suggestedEntities.indexOf(e)*10,
onthefly: true,
name: e.text,
address: {
id: e.current_household_address.address_id,
},
locationType: locationType
});
}
}
)
return locations;
};
const makeConcernedThirdPartiesLocation = (locationType, store) => {
let locations = [];
store.getters.suggestedEntities.forEach(
(e) => {
if (e.type === 'thirdparty' && e.address !== null){
locations.push({
type: 'location',
id: -store.getters.suggestedEntities.indexOf(e)*10,
onthefly: true,
name: e.text,
address: { id: e.address.address_id },
locationType: locationType
});
}
}
)
return locations;
};
const makeAccompanyingPeriodLocation = (locationType, store) => {
const accPeriodLocation = store.state.activity.accompanyingPeriod.location;
return {
type: 'location',
id: -1,
onthefly: true,
name: '__AccompanyingCourseLocation__',
address: {
id: accPeriodLocation.address_id,
text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}`
},
locationType: locationType
}
};
export default function prepareLocations(store) {
// find the locations
let allLocations = getLocations().then(
(results) => {
store.commit('addAvailableLocationGroup', {
locationGroup: 'Autres localisations',
locations: results
});
}
);
let currentLocation = getUserCurrentLocation().then(
userCurrentLocation => {
if (null !== userCurrentLocation) {
store.commit('addAvailableLocationGroup', {
locationGroup: 'Ma localisation',
locations: [userCurrentLocation]
});
}
}
);
let partiesLocations = [], partyPromise;
['person', 'thirdparty'].forEach(kind => {
partyPromise = getLocationTypeByDefaultFor(kind).then(
(kindLocationType) => {
if (kindLocationType) {
let concernedKindLocations;
if (kind === 'person') {
concernedKindLocations = makeConcernedPersonsLocation(kindLocationType, store);
// add location for the parcours into suggestions
const personLocation = makeAccompanyingPeriodLocation(kindLocationType, store);
store.commit('addAvailableLocationGroup', {
locationGroup: 'Localisation du parcours',
locations: [personLocation]
});
} else {
concernedKindLocations = makeConcernedThirdPartiesLocation(kindLocationType, store);
}
store.commit('addAvailableLocationGroup', {
locationGroup: kind === 'person' ? 'Usagers concernés' : 'Tiers concernés',
locations: concernedKindLocations,
});
}
}
);
partiesLocations.push(partyPromise);
});
// when all location are loaded
Promise.all([allLocations, currentLocation, ...partiesLocations]).then(() => {
console.log('current location in activity', store.state.activity.location);
console.log('default loation id', window.default_location_id);
if (window.default_location_id) {
for (let group of store.state.availableLocations) {
console.log(group);
let location = group.locations.find((l) => l.id === window.default_location_id);
console.log(location);
if (location !== undefined) {
store.dispatch('updateLocation', location);
break;
}
}
}
});
}

View File

@ -18,7 +18,8 @@ use Symfony\Component\HttpFoundation\Request;
// This check prevents access to debug front controllers that are deployed by accident to production servers. // This check prevents access to debug front controllers that are deployed by accident to production servers.
// Feel free to remove this, extend it, or make something more sophisticated. // Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP']) if (
isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR']) || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1'], true) || \PHP_SAPI === 'cli-server') || !(in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1'], true) || \PHP_SAPI === 'cli-server')
) { ) {

View File

@ -1,110 +0,0 @@
<h2 class="badge-title">
<span class="title_label">
{% if activity.date %}
<h3>{{ activity.date|format_date('short') }}</h3>
{% endif %}
<div class="duration">
{% if activity.durationTime and t.durationTimeVisible %}
<p>
<abbr class="fa fa-fw fa-hourglass-end" title="{{ 'Duration Time'|trans }}"></abbr>
{{ activity.durationTime|date('H:i') }}
</p>
{% endif %}
{% if activity.travelTime and t.travelTimeVisible %}
<p>
<abbr class="fa fa-fw fa-car" title="{{ 'Travel time'|trans }}"></abbr>
{{ activity.travelTime|date('H:i') }}
</p>
{% endif %}
</div>
</span>
<span class="title_action">
{{ activity.type.name | localize_translatable_string }}
{% if activity.emergency %}
<span class="badge bg-danger rounded-pill fs-6">{{ 'Emergency'|trans|upper }}</span>
{% endif %}
<ul class="small_in_title mt-3">
{% if activity.sentReceived is not empty and t.sentReceivedVisible %}
<li>
<span class="item-key">{{ 'Sent received'|trans ~ ' : ' }}</span>
<b>{{ activity.sentReceived|capitalize|trans }}</b>
</li>
{% endif %}
{% if activity.location and t.locationVisible %}
<li>
<span class="item-key">{{ 'location'|trans ~ ': ' }}</span>
<b>
<span>{{ activity.location.locationType.title|localize_translatable_string }}</span>
{{ activity.location.name }}
</b>
</li>
{% endif %}
{% if activity.user and t.userVisible %}
<li>
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
<b>{{ activity.user.usernameCanonical }}</b>
</li>
{% endif %}
<li class="associated-persons">
<span class="item-key">{{ 'Participants'|trans ~ ' : ' }}</span>
{% for p in activity.personsAssociated %}
<span class="badge-person">{{ p|chill_entity_render_box }}</span>
{% endfor %}
</li>
</ul>
<ul class="list-content my-3">
{%- if t.reasonsVisible -%}
{%- if activity.reasons is not empty -%}
<li class="reasons">
{% for r in activity.reasons %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
{%- if t.socialIssuesVisible %}
{%- if activity.socialIssues is not empty -%}
<li class="social-issues">
{% for r in activity.socialIssues %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
{%- if t.socialActionsVisible -%}
{%- if activity.socialActions is not empty -%}
<li class="social-actions">
{% for r in activity.socialActions %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
</ul>
</span>
</h2>
{% 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 %}

View File

@ -3,6 +3,14 @@
{{ path(pathname, parms) }} {{ path(pathname, parms) }}
{% endmacro %} {% endmacro %}
{% macro insert_onthefly(type, entity) %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: true,
targetEntity: { name: type, id: entity.id },
buttonText: entity|chill_entity_render_string
} %}
{% endmacro %}
{% macro computeWidth(nbBlocks) %} {% macro computeWidth(nbBlocks) %}
{{ 'flex-basis: ' ~ (100 / nbBlocks)|round(1) ~ '%;' }} {{ 'flex-basis: ' ~ (100 / nbBlocks)|round(1) ~ '%;' }}
{% endmacro %} {% endmacro %}
@ -13,6 +21,7 @@
{% set blocks = blocks|merge([{ {% set blocks = blocks|merge([{
'title': 'Others persons'|trans, 'title': 'Others persons'|trans,
'items': entity.persons, 'items': entity.persons,
'type': 'person',
'path' : 'chill_person_view', 'path' : 'chill_person_view',
'key' : 'person_id' 'key' : 'person_id'
}]) %} }]) %}
@ -20,11 +29,13 @@
{% set blocks = blocks|merge([{ {% set blocks = blocks|merge([{
'title': 'Persons in accompanying course'|trans, 'title': 'Persons in accompanying course'|trans,
'items': entity.personsAssociated, 'items': entity.personsAssociated,
'type': 'person',
'path' : 'chill_person_view', 'path' : 'chill_person_view',
'key' : 'person_id' 'key' : 'person_id'
},{ },{
'title': 'Third persons'|trans, 'title': 'Third persons'|trans,
'items': entity.personsNotAssociated, 'items': entity.personsNotAssociated,
'type': 'person',
'path' : 'chill_person_view', 'path' : 'chill_person_view',
'key' : 'person_id', 'key' : 'person_id',
}]) %} }]) %}
@ -34,6 +45,7 @@
{% set blocks = blocks|merge([{ {% set blocks = blocks|merge([{
'title': 'Third parties'|trans, 'title': 'Third parties'|trans,
'items': entity.thirdParties, 'items': entity.thirdParties,
'type': 'thirdparty',
'path' : 'chill_crud_3party_3party_view', 'path' : 'chill_crud_3party_3party_view',
'key' : 'id', 'key' : 'id',
}]) %} }]) %}
@ -42,6 +54,7 @@
{% set blocks = blocks|merge([{ {% set blocks = blocks|merge([{
'title': 'Users concerned'|trans, 'title': 'Users concerned'|trans,
'items': entity.users, 'items': entity.users,
'type': 'user',
'key' : 'id', 'key' : 'id',
}]) %} }]) %}
{% endif %} {% endif %}
@ -59,22 +72,12 @@
<ul class="list-content"> <ul class="list-content">
{% for item in bloc.items %} {% for item in bloc.items %}
<li> <li>
{% if bloc.path is defined %} {% if bloc.type == 'user' %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}"> <span class="badge-user">
<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 }) }}
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span> </span>
</a>
{% else %} {% else %}
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}"> {{ _self.insert_onthefly(bloc.type, item) }}
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
{% endif %} {% endif %}
</li> </li>
{% endfor %} {% endfor %}
@ -96,20 +99,12 @@
<ul class="list-content"> <ul class="list-content">
{% for item in bloc.items %} {% for item in bloc.items %}
<li> <li>
{% if bloc.path is defined %} {% if bloc.type == 'user' %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}"> <span class="badge-user">
<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 }) }}
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span> </span>
</a>
{% else %} {% else %}
{{ item|chill_entity_render_box({ {{ _self.insert_onthefly(bloc.type, item) }}
'render': 'raw',
'addAltNames': false
}) }}
{% endif %} {% endif %}
</li> </li>
{% endfor %} {% endfor %}
@ -126,24 +121,18 @@
<div class="wl-row"> <div class="wl-row">
{% if bloc.items|length > 0 %} {% if bloc.items|length > 0 %}
<div class="wl-col title"> <div class="wl-col title">
<h4>{{ bloc.title }}</h4> <h3>{{ bloc.title }}</h3>
</div> </div>
<div class="wl-col list"> <div class="wl-col list">
{% for item in bloc.items %} {% for item in bloc.items %}
<span class="wl-item {% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}"> <span class="wl-item">
{% if bloc.path is defined %} {% if bloc.type == 'user' %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}"> <span class="badge-user">
{{ item|chill_entity_render_box({ {{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
'render': 'raw', </span>
'addAltNames': false
}) }}
</a>
{% else %} {% else %}
{{ item|chill_entity_render_box({ {{ _self.insert_onthefly(bloc.type, item) }}
'render': 'raw',
'addAltNames': false
}) }}
{% endif %} {% endif %}
</span> </span>

View File

@ -1,5 +1,12 @@
<h1>{{ "Update activity"|trans }}</h1> <h1>
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2> {{ "Update activity"|trans }}
</h1>
<h2 class="badge-title mb-5">
<span class="title_label"></span>
<span class="title_action">
{{ entity.type.name | localize_translatable_string }}
</span>
</h2>
{{ form_start(edit_form) }} {{ form_start(edit_form) }}
{{ form_errors(edit_form) }} {{ form_errors(edit_form) }}
@ -37,7 +44,7 @@
{% endif %} {% endif %}
{%- if edit_form.persons is defined or edit_form.thirdParties is defined or edit_form.users is defined -%} {%- if edit_form.persons is defined or edit_form.thirdParties is defined or edit_form.users is defined -%}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2> <h2 class="chill-blue">{{ 'Concerned groups'|trans }}</h2>
{%- if edit_form.persons is defined -%} {%- if edit_form.persons is defined -%}
{{ form_widget(edit_form.persons) }} {{ form_widget(edit_form.persons) }}
@ -53,7 +60,7 @@
{% endif %} {% endif %}
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2> <h2 class="chill-blue">{{ 'Activity data'|trans }}</h2>
{%- if edit_form.date is defined -%} {%- if edit_form.date is defined -%}
{{ form_row(edit_form.date) }} {{ form_row(edit_form.date) }}
@ -73,7 +80,6 @@
{% endif %} {% endif %}
{%- if edit_form.comment is defined -%} {%- if edit_form.comment is defined -%}
{# TODO .. public and private #}
{{ form_row(edit_form.comment) }} {{ form_row(edit_form.comment) }}
{% endif %} {% endif %}
@ -97,16 +103,16 @@
{% set accompanying_course_id = accompanyingCourse.id %} {% set accompanying_course_id = accompanyingCourse.id %}
{% endif %} {% endif %}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">
<li class="cancel"> <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"> <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 }} {{ 'Cancel'|trans }}
</a> </a>
</li> </li>
<li> <li>
<button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button> <button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button>
</li> </li>
</ul> </ul>
{{ form_end(edit_form) }}
{{ form_end(edit_form) }}
{# {{ form(delete_form) }} #} {# {{ form(delete_form) }} #}

View File

@ -10,49 +10,196 @@
{% for activity in activities %} {% for activity in activities %}
{% set t = activity.type %} {% set t = activity.type %}
<div class="item-bloc"> <div class="item-bloc">
<div class="item-row"> <div class="item-row">
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %} <div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
{% if activity.date %}
<p class="date-label">
{{ activity.date|format_date('short') }}
</p>
{% endif %}
</div>
<div class="wl-col list">
<h2 class="badge-title">
<span class="title_label"></span>
<span class="title_action">
{{ activity.type.name | localize_translatable_string }}
{% if activity.emergency %}
<span class="badge bg-danger rounded-pill fs-6 float-end">{{ 'Emergency'|trans|upper }}</span>
{% endif %}
</span>
</h2>
</div>
</div>
</div>
</div> </div>
{% if activity.comment.comment is not empty <div class="item-row column separator">
or activity.persons|length > 0 <div class="wrap-list">
or activity.thirdParties|length > 0 {% if activity.location and t.locationVisible %}
or activity.users|length > 0 <div class="wl-row">
%} <div class="wl-col title"><h3>{{ 'location'|trans }}</h3></div>
<div class="main"> <div class="wl-col list">
{% if activity.comment.comment is not empty %} <p class="wl-item">
{{ activity.comment|chill_entity_render_box({ <span>{{ activity.location.locationType.title|localize_translatable_string }}</span>
'disable_markdown': false, {{ activity.location.name }}
'limit_lines': 3, </p>
'metadata': false, </div>
}) }} </div>
{% endif %} {% endif %}
{% if activity.sentReceived is not empty and t.sentReceivedVisible %}
<div class="wl-row">
<div class="wl-col title"><h3>{{ 'Sent received'|trans }}</h3></div>
<div class="wl-col list">
<p class="wl-item">
{{ activity.sentReceived|capitalize|trans }}
</p>
</div>
</div>
{% endif %}
{% if activity.user and t.userVisible %}
<div class="wl-row">
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
<div class="wl-col list">
<p class="wl-item">
{{ activity.user.usernameCanonical|chill_entity_render_string|capitalize }}
</p>
</div>
</div>
{% endif %}
</div>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with { {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
'context': context, 'context': context,
'with_display': 'row', 'with_display': 'wrap-list',
'entity': activity, 'entity': activity,
'badge_person': true 'badge_person': true
} %} } %}
<div class="wrap-list">
{%- if activity.reasons is not empty and t.reasonsVisible -%}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Reasons'|trans }}</h3>
</div>
<div class="wl-col list">
{% for r in activity.reasons %}
<p class="wl-item reasons">
{{ r|chill_entity_render_box }}
</p>
{% endfor %}
</div>
</div>
{% endif %}
{%- if activity.socialIssues is not empty and t.socialIssuesVisible -%}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Social issues'|trans }}</h3>
</div>
<div class="wl-col list">
{% for r in activity.socialIssues %}
<p class="wl-item social-issues">
{{ r|chill_entity_render_box }}
</p>
{% endfor %}
</div>
</div>
{% endif %}
{%- if activity.socialActions is not empty and t.socialActionsVisible -%}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Social actions'|trans }}</h3>
</div>
<div class="wl-col list">
{% for r in activity.socialActions %}
<p class="wl-item social-actions">
{{ r|chill_entity_render_box }}
</p>
{% endfor %}
</div>
</div>
{% endif %}
{% if activity.comment.comment is not empty and is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Comment'|trans }}</h3>
</div>
<div class="wl-col list">
{{ activity.comment|chill_entity_render_box({
'disable_markdown': false,
'limit_lines': 3,
'metadata': false
}) }}
</div>
</div>
{% endif %}
{# Only if ACL SEE_DETAILS AND/OR only on template SHOW ??
durationTime
travelTime
comment
documents
attendee
#}
</div>
</div> </div>
{% endif %}
<div class="item-row separator"> <div class="item-row separator">
<div class="updatedBy"></div>
<ul class="record_actions"> <ul class="record_actions">
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
{#
Disable person_id in following links, for redirect to accompanyingCourse context
#}
{% set person_id = null %}
{% set accompanying_course_id = activity.accompanyingPeriod.id %}
<li>
<a href="{{ chill_path_add_return_path('chill_activity_activity_list',{
'accompanying_period_id': accompanying_course_id
}) }}"
class="btn btn-primary"
title="{{ 'See activity in accompanying course context'|trans }}">
<i class="fa fa-random fa-fw"></i>
{{ 'Period number %number%'|trans({'%number%': accompanying_course_id}) }}
</a>
</li>
{% endif %}
<li> <li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" <a href="{{ path('chill_activity_activity_show', {'id': activity.id,
class="btn btn-sm btn-show "></a> 'person_id': person_id,
'accompanying_period_id': accompanying_course_id
}) }}"
class="btn btn-show"
title="{{ 'Show'|trans }}"></a>
</li> </li>
{% if no_action is not defined or no_action == false %} {% if no_action is not defined or no_action == false %}
<li> {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" <li>
class="btn btn-sm btn-update "></a> <a href="{{ path('chill_activity_activity_edit', {'id': activity.id,
</li> 'person_id': person_id,
<li> 'accompanying_period_id': accompanying_course_id
<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> class="btn btn-update"
</li> title="{{ 'Edit'|trans }}"></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,
'accompanying_period_id': accompanying_course_id
}) }}"
class="btn btn-delete"
title="{{ 'Delete'|trans }}"></a>
</li>
{% endif %}
{% endif %} {% endif %}
</ul> </ul>
</div> </div>

View File

@ -23,8 +23,8 @@
{% if is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) %} {% if is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) %}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">
<li> <li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create"> <a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
{{ 'Create'|trans }} class="btn btn-create">{{ 'Create'|trans }}
</a> </a>
</li> </li>
</ul> </ul>

View File

@ -3,10 +3,88 @@
{% set t = activity.type %} {% set t = activity.type %}
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" <a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="badge-link" title="{{ 'Show the activity'|trans }}"> class="dashboard-link" title="{{ 'Show the activity'|trans }}">
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %} <div class="dashboard">
<span class="title_label"></span>
<span class="title_action">
{%- if activity.date -%}
<p class="date-label">{{ activity.date|format_date('short') }}</p>
{%- endif -%}
<span class="like-h3">{{ activity.type.name | localize_translatable_string }}</span>
{% if activity.emergency %}
<span class="badge bg-danger rounded-pill fs-6">{{ 'Emergency'|trans|upper }}</span>
{% endif %}
<ul class="small_in_title mt-3">
{% if activity.sentReceived is not empty and t.sentReceivedVisible %}
<li>
<span class="item-key">{{ 'Sent received'|trans ~ ' : ' }}</span>
<b>{{ activity.sentReceived|capitalize|trans }}</b>
</li>
{% endif %}
{% if activity.location and t.locationVisible %}
<li>
<span class="item-key">{{ 'location'|trans ~ ': ' }}</span>
<b>
<span>{{ activity.location.locationType.title|localize_translatable_string }}</span>
{{ activity.location.name }}
</b>
</li>
{% endif %}
{% if activity.user and t.userVisible %}
<li>
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
<b>{{ activity.user.usernameCanonical }}</b>
</li>
{% endif %}
<li class="associated-persons">
<span class="item-key">{{ 'Participants'|trans ~ ' : ' }}</span>
{% for p in activity.personsAssociated %}
<span class="badge-person">{{ p|chill_entity_render_box }}</span>
{% endfor %}
</li>
</ul>
<ul class="list-content my-3">
{%- if t.reasonsVisible -%}
{%- if activity.reasons is not empty -%}
<li class="reasons">
{% for r in activity.reasons %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
{%- if t.socialIssuesVisible %}
{%- if activity.socialIssues is not empty -%}
<li class="social-issues">
{% for r in activity.socialIssues %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
{%- if t.socialActionsVisible -%}
{%- if activity.socialActions is not empty -%}
<li class="social-actions">
{% for r in activity.socialActions %}
{{ r|chill_entity_render_box }}
{% endfor %}
</li>
{%- endif -%}
{% endif %}
</ul>
</span>
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>

View File

@ -1,10 +1,16 @@
<h1>{{ "Activity creation"|trans ~ ' :' }}</h1> <h1>
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2> {{ "Activity creation"|trans }}
</h1>
<h2 class="badge-title mb-5">
<span class="title_label"></span>
<span class="title_action">
{{ entity.type.name | localize_translatable_string }}
</span>
</h2>
{{ form_start(form) }} {{ form_start(form) }}
{{ form_errors(form) }} {{ form_errors(form) }}
{%- if form.emergency is defined -%} {%- if form.emergency is defined -%}
{{ form_row(form.emergency) }} {{ form_row(form.emergency) }}
{% endif %} {% endif %}
@ -39,7 +45,7 @@
{%- if form.persons is defined or form.thirdParties is defined or form.users is defined -%} {%- if form.persons is defined or form.thirdParties is defined or form.users is defined -%}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2> <h2 class="chill-blue">{{ 'Concerned groups'|trans }}</h2>
{%- if form.persons is defined -%} {%- if form.persons is defined -%}
{{ form_widget(form.persons) }} {{ form_widget(form.persons) }}
@ -55,7 +61,7 @@
{% endif %} {% endif %}
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2> <h2 class="chill-blue">{{ 'Activity data'|trans }}</h2>
{%- if form.date is defined -%} {%- if form.date is defined -%}
{{ form_row(form.date) }} {{ form_row(form.date) }}
@ -103,7 +109,7 @@
</a> </a>
</li> </li>
<li> <li>
<button class="btn btn-create" type="submit"> <button class="btn btn-save" type="submit">
{{ 'Create'|trans }} {{ 'Create'|trans }}
</button> </button>
</li> </li>

View File

@ -1,128 +1,185 @@
{%- set t = entity.type -%} {%- set t = entity.type -%}
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%} {%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
<h1> <h1>{{ "Activity"|trans }}</h1>
{{ "Activity"|trans }}
{%- if t.emergencyVisible and entity.emergency -%}
<span class="badge bg-secondary">
{{- 'Emergency'|trans -}}
</span>
{%- endif -%}
</h1>
<dl class="chill_view_data"> <div class="flex-table">
<div class="item-bloc">
<dt class="inline">{{ 'by'|trans|capitalize }}</dt> <div class="item-row">
<dd>{{ entity.user }}</dd> <div class="wrap-list">
<div class="wl-row">
<div class="wl-col title">
{% if entity.date %}
<p class="date-label">
{{ entity.date|format_date('short') }}
</p>
{% endif %}
</div>
<div class="wl-col list">
<h2 class="badge-title">
<span class="title_label"></span>
<span class="title_action">
{{ entity.type.name | localize_translatable_string }}
{% if entity.emergency %}
<span class="badge bg-danger rounded-pill fs-6 float-end">{{ 'Emergency'|trans|upper }}</span>
{% endif %}
</span>
</h2>
</div>
</div>
</div>
</div>
<dt class="inline">{{ 'Type'|trans }}</dt> <div class="item-row separator">
<dd>{{ entity.type.name | localize_translatable_string }}</dd> <dl class="chill_view_data">
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
<dd>{{ entity.user }}</dd>
{%- if entity.scope -%} {%- if entity.scope -%}
<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>
{% endif %} <span class="scope">{{ entity.scope.name|localize_translatable_string }}</span>
</dd>
{% endif %}
{% if t.socialIssuesVisible %} {% if t.socialIssuesVisible %}
<dt class="inline">{{ 'Social issues'|trans }}</dt> <dt class="inline">{{ 'Social issues'|trans }}</dt>
<dd> <dd>
{% if entity.socialIssues|length == 0 %} {% if entity.socialIssues|length == 0 %}
<p class="chill-no-data-statement">{{ 'No social issues associated'|trans }}</p> <p class="chill-no-data-statement">{{ 'No social issues associated'|trans }}</p>
{% else %} {% else %}
{% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %} {% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %}
{% endif %} {% endif %}
</dd> </dd>
{% endif %} {% endif %}
{% if t.socialActionsVisible %} {% if t.socialActionsVisible %}
<dt class="inline">{{ 'Social actions'|trans }}</dt> <dt class="inline">{{ 'Social actions'|trans }}</dt>
<dd> <dd>
{% if entity.socialActions|length == 0 %} {% if entity.socialActions|length == 0 %}
<p class="chill-no-data-statement">{{ 'No social actions associated'|trans }}</p> <span class="chill-no-data-statement">{{ 'No social actions associated'|trans }}</span>
{% else %} {% else %}
{% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %} {% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %}
{% endif %} {% endif %}
</dd> </dd>
{% endif %} {% endif %}
{% if t.reasonsVisible %} {% if t.reasonsVisible %}
<dt class="inline">{{ 'Reasons'|trans }}</dt> <dt class="inline">{{ 'Reasons'|trans }}</dt>
{%- if entity.reasons is empty -%} <dd>
<dd><span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span></dd> {%- if entity.reasons is empty -%}
{%- else -%} <span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span>
<dd>{% for r in entity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}</dd> {%- else -%}
{%- endif -%} {% for r in entity.reasons %}{{ r|chill_entity_render_box }}{% endfor %}
{% endif %} {%- endif -%}
</dd>
{% endif %}
</dl>
</div>
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2> </div>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc', 'badge_person': 'true' } %} </div>
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2> <h2 class="chill-blue">{{ 'Concerned groups'|trans }}</h2>
<dt class="inline">{{ 'Date'|trans }}</dt> {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
<dd>{{ entity.date|format_date('long') }}</dd> 'context': context,
'with_display': 'bloc',
'badge_person': 'true'
} %}
{% if t.locationVisible %} <h2 class="chill-blue">{{ 'Activity data'|trans }}</h2>
<dt class="inline">{{ 'Activity location'|trans }}</dt>
<dd> <div class="flex-table">
{% if entity.location is not null %} <div class="item-bloc">
<p>
{{ entity.location.name }} <dl class="chill_view_data">
<span> ({{ entity.location.locationType.title|localize_translatable_string }})</span> <dt class="inline">{{ 'Date'|trans }}</dt>
</p> <dd>{{ entity.date|format_date('long') }}</dd>
{{ entity.location.address|chill_entity_render_box }}
{% else %} {% if t.locationVisible %}
<span class="chill-no-data-statement">{{ 'No address given'|trans }}</span> <dt class="inline">{{ 'Activity location'|trans }}</dt>
<dd>
{% if entity.location is not null %}
<p>
<span>{{ entity.location.locationType.title|localize_translatable_string }}</span>
{{ entity.location.name }}
</p>
<div class="ms-3">{{ entity.location.address|chill_entity_render_box }}</div>
{% else %}
<span class="chill-no-data-statement">{{ 'No address given'|trans }}</span>
{% endif %}
</dd>
{% endif %} {% endif %}
</dd>
{% endif %}
{% if t.durationTimeVisible %} {% if t.durationTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Duration Time'|trans }}</dt> <dt class="inline">{{ 'Duration Time'|trans }}</dt>
<dd>{% if entity.durationTime is not null %} <dd>
{{ entity.durationTime|date('H:i') }} {% if entity.durationTime is not null %}
{% else %} {{ entity.durationTime|date('H:i') }}
{{ 'None'|trans|capitalize }} {% else %}
{% endif %} <span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
</dd> {% endif %}
{% endif %} </dd>
{% endif %}
{% if t.travelTimeVisible %} {% if t.travelTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Travel time'|trans }}</dt> <dt class="inline">{{ 'Travel time'|trans }}</dt>
<dd>{% if entity.travelTime is not null %} <dd>
{{ entity.travelTime|date('H:i') }} {% if entity.travelTime is not null %}
{% else %} {{ entity.travelTime|date('H:i') }}
{{ 'None'|trans|capitalize }} {% else %}
{% endif %} <span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
</dd> {% endif %}
{% endif %} </dd>
{% endif %}
{% if t.commentVisible %} {% if t.commentVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'activity.comment'|trans }}</dt> <dt class="inline">{{ 'activity.comment'|trans }}</dt>
{%- if entity.comment.empty -%} <dd>
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd> {%- if entity.comment.empty -%}
{%- else -%} <span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span>
<dd>{{ entity.comment|chill_entity_render_box }}</dd> {%- else -%}
{%- endif -%} {{ entity.comment|chill_entity_render_box }}
{% endif %} {%- endif -%}
</dd>
{% endif %}
{% if t.documentsVisible and entity.documents|length > 0 %} {% if t.documentsVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt>{{ 'Documents'|trans }}</dt> <dt class="inline">{{ 'Documents'|trans }}</dt>
<dd> <dd>
<ul> {% if entity.documents|length > 0 %}
{% for d in entity.documents %} <ul>
<li>{{ m.download_button(d) }}</li> {% for d in entity.documents %}
{% endfor %} <li>{{ m.download_button(d) }}</li>
</ul> {% endfor %}
</dd> </ul>
{% endif %} {% else %}
<span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span>
{% endif %}
</dd>
{% endif %}
{% if t.attendeeVisible %} {% if t.attendeeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Attendee'|trans }}</dt> <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> <dd>
{% endif %} {% if entity.attendee is not null %}
{% if entity.attendee %}
{{ 'present'|trans|capitalize }}
{% else %}
{{ 'not present'|trans|capitalize }}
{% endif %}
{% else %}
<span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
{% endif %}
</dd>
{% endif %}
</dl> </dl>
</div>
</div>
{% set person_id = null %} {% set person_id = null %}
{% if person %} {% if person %}
@ -140,23 +197,24 @@
{{ 'Back to the list'|trans }} {{ 'Back to the list'|trans }}
</a> </a>
</li> </li>
{% if is_granted('CHILL_ACTIVITY_UPDATE', entity) %}
<li> <li>
<a class="btn btn-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"> <a class="btn btn-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}">
{{ 'Edit'|trans }} {{ 'Edit'|trans }}
</a> </a>
</li> </li>
{% endif %}
{# TODO
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %} {% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
#}
<li> <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"> <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 }} {{ 'Delete'|trans }}
</a> </a>
</li> </li>
{#
{% endif %} {% endif %}
#}
</ul> </ul>
<script>
import ShowPane from "../../../../ChillMainBundle/Resources/public/vuejs/Address/components/ShowPane";
export default {
components: {ShowPane}
}
</script>

View File

@ -8,8 +8,6 @@
{% block content -%} {% block content -%}
<div class="activity-show"> <div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %} {% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -8,8 +8,6 @@
{% block personcontent -%} {% block personcontent -%}
<div class="activity-show"> <div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
</div> </div>
{% endblock personcontent %} {% endblock personcontent %}

View File

@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter; use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use function in_array; use function in_array;
class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
@ -64,8 +65,10 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
protected function supports($attribute, $subject) protected function supports($attribute, $subject)
{ {
if ($subject instanceof Center if (
&& in_array($attribute, $this->getAttributes(), true)) { $subject instanceof Center
&& in_array($attribute, $this->getAttributes(), true)
) {
return true; return true;
} }

View File

@ -24,6 +24,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
use RuntimeException; use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use function in_array; use function in_array;
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
@ -92,6 +93,8 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
public function getRoles(): array public function getRoles(): array
{ {
return [ return [
self::SEE,
self::SEE_DETAILS,
self::CREATE_PERSON, self::CREATE_PERSON,
self::CREATE_ACCOMPANYING_COURSE, self::CREATE_ACCOMPANYING_COURSE,
self::UPDATE, self::UPDATE,

View File

@ -26,7 +26,7 @@ final class ActivityReasonAggregatorTest extends AbstractAggregatorTest
*/ */
private $aggregator; private $aggregator;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -26,7 +26,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
*/ */
private $aggregator; private $aggregator;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -26,7 +26,7 @@ final class ActivityUserAggregatorTest extends AbstractAggregatorTest
*/ */
private $aggregator; private $aggregator;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -24,7 +24,7 @@ final class CountActivityTest extends AbstractExportTest
*/ */
private $export; private $export;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -24,7 +24,7 @@ final class ListActivityTest extends AbstractExportTest
*/ */
private $export; private $export;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -26,7 +26,7 @@ final class StatActivityDurationSumTest extends AbstractExportTest
*/ */
private $export; private $export;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -25,7 +25,7 @@ final class ActivityReasonFilterTest extends AbstractFilterTest
*/ */
private $filter; private $filter;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -26,7 +26,7 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
*/ */
private $filter; private $filter;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -45,7 +45,7 @@ final class ActivityTypeTest extends KernelTestCase
*/ */
protected $user; protected $user;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -29,7 +29,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
*/ */
private static $prophet; private static $prophet;
public function setUp() protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
} }

View File

@ -31,7 +31,7 @@ final class TranslatableActivityTypeTest extends KernelTestCase
*/ */
protected $container; protected $container;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();

View File

@ -44,7 +44,7 @@ final class ActivityVoterTest extends KernelTestCase
*/ */
protected $voter; protected $voter;
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();
$this->voter = self::$kernel->getContainer() $this->voter = self::$kernel->getContainer()

View File

@ -24,6 +24,7 @@ use RuntimeException;
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 Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
use function implode; use function implode;
use function in_array; use function in_array;
use function strtr; use function strtr;

View File

@ -17,6 +17,7 @@ use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Exception\UnexpectedValueException;
use function array_merge; use function array_merge;
use function count; use function count;

View File

@ -0,0 +1,15 @@
services:
Chill\ActivityBundle\EntityListener\ActivityEntityListener:
autowire: true
autoconfigure: true
tags:
-
name: 'doctrine.orm.entity_listener'
event: 'postPersist'
entity: 'Chill\ActivityBundle\Entity\Activity'
method: 'persistActionToCourse'
-
name: 'doctrine.orm.entity_listener'
event: 'postUpdate'
entity: 'Chill\ActivityBundle\Entity\Activity'
method: 'persistActionToCourse'

View File

@ -13,6 +13,7 @@ namespace Chill\Migrations\Activity;
use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration; use Doctrine\Migrations\AbstractMigration;
use function count; use function count;
/** /**

View File

@ -0,0 +1,34 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Activity;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20211207152023 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->throwIrreversibleMigrationException('placevisible and placelabel could not be created');
}
public function getDescription(): string
{
return 'DROP place visible and place label, which are replaced by location';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE activitytype DROP placevisible');
$this->addSql('ALTER TABLE activitytype DROP placelabel');
}
}

View File

@ -146,8 +146,8 @@ User visible: Visibilité du champ Utilisateur
User label: Libellé du champ Utilisateur User label: Libellé du champ Utilisateur
Date visible: Visibilité du champ Date Date visible: Visibilité du champ Date
Date label: Libellé du champ Date Date label: Libellé du champ Date
Place visible: Visibilité du champ Lieu Location visible: Visibilité du champ Lieu
Place label: Libellé du champ Lieu Location label: Libellé du champ Lieu
Third parties visible: Visibilité du champ Tiers Third parties visible: Visibilité du champ Tiers
Third parties label: Libellé du champ Tiers Third parties label: Libellé du champ Tiers
Duration time visible: Visibilité du champ Durée Duration time visible: Visibilité du champ Durée
@ -222,3 +222,5 @@ Aggregate by activity type: Aggréger par type d'activité
Aggregate by activity reason: Aggréger par sujet de l'activité Aggregate by activity reason: Aggréger par sujet de l'activité
Last activities: Les dernières activités Last activities: Les dernières activités
See activity in accompanying course context: Voir l'activité dans le contexte du parcours d'accompagnement

View File

@ -19,6 +19,7 @@ use DateTimeImmutable;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use function random_int; use function random_int;
class LoadAsideActivity extends Fixture implements DependentFixtureInterface class LoadAsideActivity extends Fixture implements DependentFixtureInterface

View File

@ -18,10 +18,12 @@ class LoadAsideActivityCategory extends \Doctrine\Bundle\FixturesBundle\Fixture
{ {
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
foreach ([ foreach (
'Appel téléphonique', [
'Formation', 'Appel téléphonique',
] as $key => $label) { 'Formation',
] as $key => $label
) {
$category = new AsideActivityCategory(); $category = new AsideActivityCategory();
$category->setTitle(['fr' => $label]); $category->setTitle(['fr' => $label]);
$manager->persist($category); $manager->persist($category);

View File

@ -13,6 +13,7 @@ namespace Chill\AsideActivityBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
use function is_int; use function is_int;
class Configuration implements ConfigurationInterface class Configuration implements ConfigurationInterface

View File

@ -162,8 +162,12 @@ class AsideActivityCategory
public function setParent(?self $parent): self public function setParent(?self $parent): self
{ {
// cache the old result for changing it during validaiton // cache the old result for changing it during validaiton
$this->oldParent = $this->parent; if ($this->parent) {
$this->oldParent = $this->parent;
}
$this->parent = $parent; $this->parent = $parent;
dump($this);
return $this; return $this;
} }

View File

@ -32,6 +32,7 @@ use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use function in_array; use function in_array;
final class AsideActivityFormType extends AbstractType final class AsideActivityFormType extends AbstractType
@ -137,7 +138,7 @@ final class AsideActivityFormType extends AbstractType
$timezoneUTC = new DateTimeZone('GMT'); $timezoneUTC = new DateTimeZone('GMT');
/** @var DateTimeImmutable $data */ /** @var DateTimeImmutable $data */
$data = $formEvent->getData() === null ? $data = $formEvent->getData() === null ?
DateTime::createFromFormat('U', 300) : DateTime::createFromFormat('U', '300') :
$formEvent->getData(); $formEvent->getData();
$seconds = $data->getTimezone()->getOffset($data); $seconds = $data->getTimezone()->getOffset($data);
$data->setTimeZone($timezoneUTC); $data->setTimeZone($timezoneUTC);

View File

@ -13,6 +13,7 @@ namespace Chill\AsideActivityBundle\Menu;
use Knp\Menu\MenuItem; use Knp\Menu\MenuItem;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use function in_array; use function in_array;
final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface

View File

@ -26,7 +26,7 @@ final class AsideActivityControllerTest extends WebTestCase
{ {
use PrepareClientTrait; use PrepareClientTrait;
public function setUp() protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
self::bootKernel(); self::bootKernel();

View File

@ -13,6 +13,7 @@ namespace Chill\AMLI\BudgetBundle\Calculator;
use Chill\AMLI\BudgetBundle\Entity\AbstractElement; use Chill\AMLI\BudgetBundle\Entity\AbstractElement;
use OutOfBoundsException; use OutOfBoundsException;
use function array_key_exists; use function array_key_exists;
use function array_keys; use function array_keys;
use function implode; use function implode;

View File

@ -21,6 +21,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use function get_class; use function get_class;
abstract class AbstractElementController extends Controller abstract class AbstractElementController extends Controller

View File

@ -22,6 +22,7 @@ use Psr\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use function array_merge; use function array_merge;
use function count; use function count;

View File

@ -21,6 +21,7 @@ use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use function array_flip; use function array_flip;
use function asort; use function asort;

View File

@ -21,6 +21,7 @@ use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use function array_flip; use function array_flip;
class ResourceType extends AbstractType class ResourceType extends AbstractType

View File

@ -18,6 +18,7 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
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 function in_array; use function in_array;
class BudgetElementVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface class BudgetElementVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface

View File

@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use function count; use function count;
class CalendarRangeAPIController extends ApiController class CalendarRangeAPIController extends ApiController

View File

@ -28,6 +28,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\ClassMetadata;
use function in_array; use function in_array;
/** /**

View File

@ -14,6 +14,7 @@ namespace Chill\CalendarBundle\Event;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Doctrine\Persistence\Event\LifecycleEventArgs; use Doctrine\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use function array_key_exists; use function array_key_exists;
class ListenToActivityCreate class ListenToActivityCreate

View File

@ -20,7 +20,6 @@ use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\CommentType; use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
use Chill\ThirdPartyBundle\Entity\ThirdParty; use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;

View File

@ -1,6 +1,10 @@
import 'es6-promise/auto'; import 'es6-promise/auto';
import { createStore } from 'vuex'; import { createStore } from 'vuex';
import { postLocation } from 'ChillActivityAssets/vuejs/Activity/api'; import { postLocation } from 'ChillActivityAssets/vuejs/Activity/api';
import {
getLocations, getLocationTypeByDefaultFor,
getUserCurrentLocation
} from "../../../../../ChillActivityBundle/Resources/public/vuejs/Activity/api";
const debug = process.env.NODE_ENV !== 'production'; const debug = process.env.NODE_ENV !== 'production';
@ -82,7 +86,7 @@ const store = createStore({
} }
}, },
mutations: { mutations: {
// ConcernedGroups // ConcernedGroups
addPersonsInvolved(state, payload) { addPersonsInvolved(state, payload) {
//console.log('### mutation addPersonsInvolved', payload.result.type); //console.log('### mutation addPersonsInvolved', payload.result.type);
@ -94,7 +98,7 @@ const store = createStore({
state.activity.thirdParties.push(payload.result); state.activity.thirdParties.push(payload.result);
break; break;
case 'user': case 'user':
state.activity.users.push(payload.result); state.activity.users.push(payload.result);
break; break;
}; };
}, },
@ -108,7 +112,7 @@ const store = createStore({
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
break; break;
case 'user': case 'user':
state.activity.users = state.activity.users.filter(user => user !== payload); state.activity.users = state.activity.users.filter(user => user !== payload);
break; break;
}; };
}, },
@ -217,9 +221,7 @@ const store = createStore({
hiddenLocation.value = value.id; hiddenLocation.value = value.id;
} }
commit("updateLocation", value); commit("updateLocation", value);
} }
} }
}); });

View File

@ -92,8 +92,11 @@
%} %}
<div class="item-row details"> <div class="item-row details">
<div class="item-col"> <div class="item-col">
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': accompanyingCourse, 'with_display': 'row', 'entity': calendar } %} 'context': accompanyingCourse,
'with_display': 'row',
'entity': calendar
} %}
</div> </div>
{% if calendar.comment.comment is not empty %} {% if calendar.comment.comment is not empty %}
@ -123,4 +126,4 @@
</li> </li>
</ul> </ul>
{% endblock %} {% endblock %}

View File

@ -26,7 +26,7 @@ final class CalendarControllerTest extends WebTestCase
/** /**
* Setup before each test method (see phpunit doc). * Setup before each test method (see phpunit doc).
*/ */
public function setUp() protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();
$this->client = self::createClient([], [ $this->client = self::createClient([], [

View File

@ -25,6 +25,7 @@ use Symfony\Component\Console\Question\Question;
use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Parser;
use function count; use function count;
/** /**

View File

@ -23,6 +23,7 @@ use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use function array_key_exists; use function array_key_exists;
use function count; use function count;
use function in_array; use function in_array;

View File

@ -135,7 +135,7 @@ class CustomFieldDate extends AbstractCustomField
return null; return null;
} }
return $date->format('Y-m-d'); return $date->format('Y-m-d');
default: default:
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:date.' $template = 'ChillCustomFieldsBundle:CustomFieldsRendering:date.'

View File

@ -21,6 +21,7 @@ use LogicException;
use Symfony\Bridge\Twig\TwigEngine; use Symfony\Bridge\Twig\TwigEngine;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use function get_class; use function get_class;
use function gettype; use function gettype;
use function is_object; use function is_object;

View File

@ -18,7 +18,6 @@ use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\LessThanOrEqual; use Symfony\Component\Validator\Constraints\LessThanOrEqual;

View File

@ -20,6 +20,7 @@ use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use function array_key_exists; use function array_key_exists;
class CustomFieldText extends AbstractCustomField class CustomFieldText extends AbstractCustomField
@ -65,8 +66,10 @@ class CustomFieldText extends AbstractCustomField
$attrArray = []; $attrArray = [];
if (array_key_exists(self::MULTIPLE_CF_INLINE, $options) if (
&& $options[self::MULTIPLE_CF_INLINE]) { array_key_exists(self::MULTIPLE_CF_INLINE, $options)
&& $options[self::MULTIPLE_CF_INLINE]
) {
$attrArray['class'] = 'multiple-cf-inline'; $attrArray['class'] = 'multiple-cf-inline';
} }

View File

@ -20,6 +20,7 @@ use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use function count; use function count;
class CustomFieldsGroupType extends AbstractType class CustomFieldsGroupType extends AbstractType

View File

@ -15,6 +15,7 @@ use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\TransformationFailedException;
use function gettype; use function gettype;
class CustomFieldsGroupToIdTransformer implements DataTransformerInterface class CustomFieldsGroupToIdTransformer implements DataTransformerInterface

View File

@ -14,7 +14,9 @@ namespace Chill\CustomFieldsBundle\Form\DataTransformer;
use Chill\CustomFieldsBundle\Entity\CustomField; use Chill\CustomFieldsBundle\Entity\CustomField;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\DataTransformerInterface;
use function array_key_exists; use function array_key_exists;
use const JSON_THROW_ON_ERROR; use const JSON_THROW_ON_ERROR;
class JsonCustomFieldToArrayTransformer implements DataTransformerInterface class JsonCustomFieldToArrayTransformer implements DataTransformerInterface
@ -33,7 +35,9 @@ class JsonCustomFieldToArrayTransformer implements DataTransformerInterface
// @TODO: in the array_map callback, CustomField::getLabel() does not exist. What do we do here? // @TODO: in the array_map callback, CustomField::getLabel() does not exist. What do we do here?
$customFieldsLablels = array_map( $customFieldsLablels = array_map(
static function ($e) { return $e->getLabel(); }, static function ($e) {
return $e->getLabel();
},
$customFields $customFields
); );

View File

@ -15,6 +15,7 @@ use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use function array_key_exists; use function array_key_exists;
/** /**

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