Compare commits

..

5 Commits

956 changed files with 7591 additions and 33366 deletions

View File

@@ -3,3 +3,4 @@
# Run tests from root to adapt your own environment
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres?serverVersion=12&charset=utf8

View File

@@ -20,8 +20,6 @@ variables:
# Configure postgres environment variables (https://hub.docker.com/r/_/postgres/)
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
# configure database access
DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=12&charset=utf8
# fetch the chill-app using git submodules
GIT_SUBMODULE_STRATEGY: recursive
REDIS_HOST: redis
@@ -62,7 +60,7 @@ code_style:
- bin
- tests/app/vendor/
phpstan_tests:
sa_tests:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
script:
@@ -73,17 +71,6 @@ phpstan_tests:
- bin
- 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:
stage: Tests
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
@@ -92,7 +79,7 @@ unit_tests:
- 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=2G tests/app/bin/console cache:clear --env=test
- php -d memory_limit=4G bin/phpunit --colors=never
- php -d memory_limit=3G bin/phpunit --colors=never
artifacts:
expire_in: 30 min
paths:

View File

@@ -11,185 +11,10 @@ and this project adheres to
## Unreleased
<!-- write down unreleased development here -->
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
* renomme date de début en date d'ouverture dans le formulaire parcours
## Test releases
### test release 2021-01-31
[fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
[homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
* [person] accompanying course: close modal when edit participation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
* [person] accompanying course: treat validation error when editing on-the-fly entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
* [activity] show activity attendee (présence) in the activity list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/412)
* [activity] admin: change validation rule for social action visible field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/413)
* [parcours]: component added to change the opening date of a parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/411)
* [search]: listing of parcours display changed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/410)
* [user]: page with accompanying periods to which is user is referent (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/408)
* [person] age added to renderstring + renderbox/ vue component created to display person text (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/389)
* [household member editor] allow to push to existing household
* [workflow][notification] improve how notifications and workflows are 'attached' to entities: contextual list, counter, buttons and vue modal
### test release 2021-01-28
* [person] improve filiations vis graph: disable physics, use chill colors for persons-households-course, increase label of relations, remove labels on household arrows and other improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/286, https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/362)
* [activity] Order activity by date and by id (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/364)
* [main] increase length of 4 Address fields (change to TEXT, no size limits) (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/277)
* [main] Add confidential option for address, in edit and view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/165)
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
* [person] Add residential address entity, form and list for each person
* [aside_activity]: dynamicUserPickerType used (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/399)
* dispatching list
### test release 2021-01-26
* [parcours] comments truncated if too long + link added (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/406)
* [person]: possibility to add person resources (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/382)
* [person ressources]: module added
### test release 2022-01-24
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
* [notification: formulaire création] descend la box avec la description dans le bas du formulaire
* [notification for activity]: fix link to activity
* [notification] add "URGENT" before accompanying course with emergency = true
* [notification] add a "read more" button on system notification
* [notification] add `[Chill]` in the subject of each notification, automatically
* [notification] add a counter for notification in activity list and accompanying period list, and search results
* [parcours] bugfix if deathdate is not defined (eg. for a thirdparty) parcours is still displayed. Gave error before.
* [workflow] add breadcrumb to show steps
* [popover] add popover html popup mechanism (used by workflow breadcrumb)
* [templates] improve updatedBy macro in item metadatas
* [parcours]: bug fix when comment is pinned all other comments remain in the collection (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/385)
* [workflow]
* add My workflow section with my opened subscriptions
* apply workflow on documents, accompanyingCourseWork and Evaluations
* [wopi-link] a new vue component allow to open wopi link in a fullscreen chill-themed modal
### test release 2022-01-19
* vuejs: add dead information on all on-the-fly person render boxes, in vis graph and other templates (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/271)
* [thirdparty] fix bug in 3rd party view: types was replaced by thirdPartyTypes
* [main] location form type: fix unmapped address field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/246)
* [activity] fix wrong import of js assets for adding and viewing documents in activity (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/83 & https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/176)
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
* [forms] dynamic picker types for user/person/thirdparty types created (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/386)
### test release 2022-01-17
* [main] Add editableByUser field to locationType entity, adapt the admin template and add this condition in the location-type endpoint (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/297)
* [main] Add mainLocation field to User entity and add it in user form type
* rewrite page which allow to select activity
* [main] Add mainLocation field to User entity and add it in user form type
* [course list in person context] show full username/label for ref
* [accompanying period work] remove the possibility to generate document from an accompanying period work
* vuejs: add validation on required fields for AddPerson, Address and Location components
* vuejs: treat 422 validation errors in locations and AddPerson components
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
## Test releases
* vuejs: add validation on required fields for AddPerson, Address and Location components
* vuejs: treat 422 validation errors in locations and AddPerson components
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
### test release 2022-01-12
* fix thirdparty normalizer on telephone field: https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/322
### test release 2022-01-11
* vuejs: translate in French all multiselect widgets
* [address] define address lines according postal standards for France and Belgium (default) and change AddressRender, chill_entity_render_box and AddressRenderBox.vue
* [household] change translations (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [household] add address i18n in household component (champs-libres/departement-de-la-vendee/accent-suivi-developpement#158)
* [household] add on the fly i18n in household component
* [household] redirect to the household page when a household is created from a person (champs-libres/departement-de-la-vendee/accent-suivi-developpement#175)
* [household] household member editor: display alert if some members have already an household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#172)
* [household] household member editor: do not add in new members if the member is included in the members of household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#123)
* [household] household member editor: remove markNoAddress button (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [person]: ordering fields in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* [person]: Add email and alt names in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* [accompanyingCourse] Add a delete action and delete buttons to delete a accompanying course when step = DRAFT (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/64)
* [accompanyingCourse] Add a administrative location in the accompanying course, set the user current location as default, allow to select a location in a select field and do not allow to confirm the accompanying course if location is empty.
* [accompanyingCourse] Add the administrative location in the available variables for document generation
* 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
* [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)
* [accompanyingCourse] improve masonry on resume page, add origin
* [notification] new notification interface, can be associated to AccompanyingCourse/Period, Activities.
* List notifications, show, and comment in User section
* Notify button and contextual notification box on associated objects pages
* [accompanyingCourse] add a comment for each resource associated. A modal allow to save comment. Comment is displayed in on-the-fly show modal of the accompanyingCourse context (edit page + resume page).
### 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 releases
### Test release 2021-11-19 - bis
@@ -198,7 +23,6 @@ and this project adheres to
* [activity] layout for issues / actions
* [activity][bugfix] in edit mode, the form will now load the social action list
### 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)
@@ -226,9 +50,6 @@ 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
* [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
* [activity] delete admin_user_show in twig template because this route is not defined and should be defined
@@ -343,7 +164,7 @@ and this project adheres to
* fast creation buttons
* add ordering for types
* [AccompanyingCourse Resume page] dashboard for AccompanyingCourseWork and for Activities;
* [AccompanyingCourse Resume page] badge-title for AccompanyingCourseWork and for Activities;
* Improve badges behaviour with small screens;
* [ThirdParty]:

View File

@@ -397,6 +397,7 @@ Créer une liste de suggestions à enlever (avec une croix rouge cliquable, l'an
<li>
<span>
item
<a></a>
</span>
</li>
</ul>
@@ -404,8 +405,7 @@ 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)
```html
<div class="item-title">
<span>title</span>
title
<a></a>
</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,84 +1,79 @@
{
"name": "chill-project/chill-bundles",
"description": "Most used bundles for chill-project",
"license": "AGPL-3.0-only",
"type": "library",
"description": "Most used bundles for chill-project",
"keywords": [
"chill",
"social worker"
],
"license": "AGPL-3.0-only",
"require": {
"php": "^7.4",
"champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
"champs-libres/wopi-bundle": "dev-master#59b468503b9413f8d588ef9e626e7675560db3d8",
"champs-libres/wopi-lib": "dev-master#0e1da19bb6de820080b8651867a7e475be590060",
"champs-libres/async-uploader-bundle": "dev-sf4",
"champs-libres/wopi-bundle": "dev-master",
"composer/package-versions-deprecated": "^1.10",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"erusev/parsedown": "^1.7",
"graylog2/gelf-php": "^1.5",
"knplabs/knp-menu": "^3.1",
"knplabs/knp-menu-bundle": "^3.0",
"knplabs/knp-time-bundle": "^1.12",
"league/csv": "^9.7.1",
"nyholm/psr7": "^1.4",
"ocramius/package-versions": "^1.10",
"phpoffice/phpspreadsheet": "^1.16",
"ramsey/uuid-doctrine": "^1.7",
"sensio/framework-extra-bundle": "^5.5",
"spomky-labs/base64url": "^2.0",
"symfony/asset": "^4.4",
"symfony/browser-kit": "^4.4",
"symfony/css-selector": "^4.4",
"symfony/expression-language": "^4.4",
"symfony/form": "^4.4",
"symfony/framework-bundle": "^4.4",
"symfony/intl": "^4.4",
"symfony/mailer": "^5.4",
"symfony/mime": "^5.4",
"symfony/asset": "4.*",
"symfony/browser-kit": "^5.2",
"symfony/css-selector": "^5.2",
"symfony/expression-language": "4.*",
"symfony/form": "4.*",
"symfony/intl": "4.*",
"symfony/mime": "^4 || ^5",
"symfony/monolog-bundle": "^3.5",
"symfony/security-bundle": "^4.4",
"symfony/serializer": "^5.3",
"symfony/security-bundle": "4.*",
"symfony/serializer": "^5.2",
"symfony/swiftmailer-bundle": "^3.5",
"symfony/templating": "^4.4",
"symfony/translation": "^4.4",
"symfony/templating": "4.*",
"symfony/translation": "4.*",
"symfony/twig-bundle": "^4.4",
"symfony/validator": "^4.4",
"symfony/validator": "4.*",
"symfony/webpack-encore-bundle": "^1.11",
"symfony/workflow": "^4.4",
"symfony/yaml": "^4.4",
"twig/extra-bundle": "^3.0",
"symfony/workflow": "4.*",
"symfony/yaml": "4.*",
"twig/extra-bundle": "^2.12 || ^3.0",
"twig/intl-extra": "^3.0",
"twig/markdown-extra": "^3.3",
"twig/string-extra": "^3.3",
"twig/twig": "^3.0"
"twig/twig": "^2.12 || ^3.0"
},
"conflict": {
"symfony/symfony": "*"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3",
"drupol/php-conventions": "^5",
"fakerphp/faker": "^1.13",
"nelmio/alice": "^3.8",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": ">= 7.5",
"phpunit/phpunit": "^7.0",
"symfony/debug-bundle": "^5.1",
"symfony/dotenv": "^4.4",
"symfony/dotenv": "^5.1",
"symfony/maker-bundle": "^1.20",
"symfony/phpunit-bridge": "^4.4",
"symfony/stopwatch": "^4.4",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4"
"symfony/phpunit-bridge": "^5.2",
"symfony/stopwatch": "^5.1",
"symfony/var-dumper": "4.*",
"symfony/web-profiler-bundle": "^5.0"
},
"conflict": {
"symfony/symfony": "*"
"config": {
"bin-dir": "bin",
"vendor-dir": "tests/app/vendor"
},
"autoload": {
"psr-4": {
"Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle",
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
"Chill\\BudgetBundle\\": "src/Bundle/ChillBudgetBundle",
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
"Chill\\CustomFieldsBundle\\": "src/Bundle/ChillCustomFieldsBundle",
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
"Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
@@ -87,6 +82,9 @@
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle",
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
"Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src"
}
},
@@ -96,23 +94,12 @@
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
}
},
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"ergebnis/composer-normalize": true,
"ocramius/package-versions": true,
"phpro/grumphp": true,
"phpstan/extension-installer": true
},
"bin-dir": "bin",
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "tests/app/vendor"
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"auto-scripts": {
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"cache:clear": "symfony-cmd"
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
}
}
}

View File

@@ -91,9 +91,7 @@ class CountPerson implements ExportInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
// 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();

View File

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

View File

@@ -12,28 +12,3 @@ parameters:
tasks.phpcsfixer.allow_risky: true
tasks.phpcsfixer.diff: true
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/"

3
package.json.txt Normal file
View File

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

View File

@@ -10,6 +10,16 @@ parameters:
count: 1
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\\.$#"
count: 3
@@ -80,6 +90,11 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
-
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Foreach overwrites \\$action with its value variable\\.$#"
count: 1

View File

@@ -30,6 +30,36 @@ parameters:
count: 2
path: src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php
-
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Parameter \\$action of method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:countBySocialActionWithDescendants\\(\\) has invalid type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\SocialAction\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$action$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$limit$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$offset$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Undefined variable\\: \\$orderBy$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Variable variables are not allowed\\.$#"
count: 4

View File

@@ -417,6 +417,15 @@ parameters:
count: 1
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:
"""
@@ -426,6 +435,15 @@ parameters:
count: 1
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:
"""
@@ -507,6 +525,24 @@ parameters:
count: 1
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:
"""
@@ -859,6 +895,11 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php
-
message: "#^Call to deprecated method setTimeout\\(\\) of class Redis\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverLocker.php
-
message:
"""
@@ -1270,6 +1311,16 @@ parameters:
count: 1
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:
"""

View File

@@ -315,6 +315,11 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/TokenManager.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
path: src/Bundle/ChillMainBundle/Templating/Entity/AddressRender.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -400,6 +405,11 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
-
message: "#^Method Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\AccompanyingPeriodWorkRepository\\:\\:buildQueryBySocialActionWithDescendants\\(\\) has invalid return type Chill\\\\PersonBundle\\\\Repository\\\\AccompanyingPeriod\\\\QueryBuilder\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +0,0 @@
<?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

@@ -31,7 +31,6 @@ use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
@@ -39,7 +38,6 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Serializer\SerializerInterface;
use function array_key_exists;
@@ -256,7 +254,7 @@ final class ActivityController extends AbstractController
if ($person instanceof Person) {
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
$activities = $this->activityACLAwareRepository
->findByPerson($person, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']);
->findByPerson($person, ActivityVoter::SEE, 0, null);
$event = new PrivacyEvent($person, [
'element_class' => Activity::class,
@@ -269,7 +267,7 @@ final class ActivityController extends AbstractController
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
$activities = $this->activityACLAwareRepository
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']);
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE);
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
}
@@ -309,10 +307,8 @@ final class ActivityController extends AbstractController
$activityData = $request->query->get('activityData');
}
if (
!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType
|| !$activityType->isActive()
) {
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType
|| !$activityType->isActive()) {
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
if (null !== $activityData) {
@@ -472,21 +468,20 @@ final class ActivityController extends AbstractController
public function showAction(Request $request, int $id): Response
{
$entity = $this->activityRepository->find($id);
$view = null;
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
$accompanyingPeriod = $entity->getAccompanyingPeriod();
$person = $entity->getPerson();
[$person, $accompanyingPeriod] = $this->getEntity($request);
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
} elseif ($person instanceof Person) {
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
} else {
throw new RuntimeException('the activity should be linked with a period or person');
}
$entity = $this->activityRepository->find($id);
if (null === $entity) {
throw $this->createNotFoundException('Unable to find Activity entity.');
}
if (null !== $accompanyingPeriod) {
@@ -495,7 +490,8 @@ final class ActivityController extends AbstractController
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
}
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $entity);
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
$deleteForm = $this->createDeleteForm($entity->getId(), $person, $accompanyingPeriod);

View File

@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Chill\ActivityBundle\Form\ActivityReasonCategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;

View File

@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;

View File

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

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Entity;
use Chill\ActivityBundle\Validator\Constraints as ActivityValidator;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Entity\Document;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Chill\MainBundle\Entity\HasCenterInterface;
@@ -47,8 +47,7 @@ use Symfony\Component\Serializer\Annotation\SerializedName;
* })
* @ActivityValidator\ActivityValidity
*
* TODO see if necessary
* UserCircleConsistency(
* @UserCircleConsistency(
* "CHILL_ACTIVITY_SEE_DETAILS",
* getUserFunction="getUser",
* path="scope")
@@ -67,7 +66,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
* @SerializedName("activityType")
* @ORM\JoinColumn(name="type_id")
*/
@@ -75,19 +74,16 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/**
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
* @Groups({"docgen:read"})
*/
private ?ActivityPresence $attendee = null;
/**
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
* @Groups({"docgen:read"})
*/
private CommentEmbeddable $comment;
/**
* @ORM\Column(type="datetime")
* @Groups({"docgen:read"})
*/
private DateTime $date;
@@ -103,7 +99,6 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/**
* @ORM\Column(type="boolean", options={"default": false})
* @Groups({"docgen:read"})
*/
private bool $emergency = false;
@@ -111,13 +106,13 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
* @groups({"read", "docgen:read"})
* @groups({"read"})
*/
private ?Location $location = null;
@@ -128,45 +123,42 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private ?Collection $persons = null;
/**
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
* @Groups({"docgen:read"})
*/
private Collection $reasons;
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
* @Groups({"docgen:read"})
*/
private ?Scope $scope = null;
/**
* @ORM\Column(type="string", options={"default": ""})
* @Groups({"docgen:read"})
*/
private string $sentReceived = '';
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private Collection $socialActions;
/**
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private Collection $socialIssues;
/**
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private ?Collection $thirdParties = null;
@@ -177,13 +169,12 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
/**
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
* @Groups({"docgen:read"})
*/
private User $user;
/**
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
* @Groups({"read", "docgen:read"})
* @Groups({"read"})
*/
private ?Collection $users = null;
@@ -199,7 +190,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
$this->socialActions = new ArrayCollection();
}
public function addDocument(StoredObject $document): self
public function addDocument(Document $document): self
{
$this->documents[] = $document;
@@ -310,18 +301,6 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this->documents;
}
/**
* @Groups({"docgen:read"})
*/
public function getDurationMinute(): int
{
if (null === $this->durationTime) {
return 0;
}
return (int) round(($this->durationTime->getTimestamp() + $this->durationTime->getOffset()) / 60.0, 0);
}
public function getDurationTime(): ?DateTime
{
return $this->durationTime;
@@ -422,18 +401,6 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this->travelTime;
}
/**
* @Groups({"docgen:read"})
*/
public function getTravelTimeMinute(): int
{
if (null === $this->travelTime) {
return 0;
}
return (int) round(($this->travelTime->getTimestamp() + $this->travelTime->getOffset()) / 60.0, 0);
}
/**
* @deprecated
*/
@@ -457,7 +424,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
return $this->getEmergency();
}
public function removeDocument(StoredObject $document): void
public function removeDocument(Document $document): void
{
$this->documents->removeElement($document);
}

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* Class ActivityPresence.
@@ -32,14 +31,11 @@ class ActivityPresence
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @Serializer\Groups({"docgen:read"})
*/
private ?int $id;
/**
* @ORM\Column(type="json")
* @Serializer\Groups({"docgen:read"})
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
*/
private array $name = [];

View File

@@ -13,10 +13,8 @@ namespace Chill\ActivityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException;
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* Class ActivityType.
@@ -120,7 +118,6 @@ class ActivityType
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"docgen:read"})
*/
private ?int $id;
@@ -136,8 +133,7 @@ class ActivityType
/**
* @ORM\Column(type="json")
* @Groups({"read", "docgen:read"})
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
* @Groups({"read"})
*/
private array $name = [];
@@ -167,6 +163,16 @@ class ActivityType
*/
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": ""})
*/
@@ -194,6 +200,7 @@ class ActivityType
/**
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
* @Assert\EqualTo(propertyPath="socialIssuesVisible", message="This parameter must be equal to social issue parameter")
*/
private int $socialActionsVisible = self::FIELD_INVISIBLE;
@@ -263,23 +270,6 @@ class ActivityType
*/
private int $userVisible = self::FIELD_REQUIRED;
/**
* @Assert\Callback
*
* @param mixed $payload
*/
public function checkSocialActionsVisibility(ExecutionContextInterface $context, $payload)
{
if ($this->socialIssuesVisible !== $this->socialActionsVisible) {
if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) {
$context
->buildViolation('The socialActionsVisible value is not compatible with the socialIssuesVisible value')
->atPath('socialActionsVisible')
->addViolation();
}
}
}
/**
* Get active
* return true if the type is active.
@@ -416,6 +406,16 @@ class ActivityType
return $this->personVisible;
}
public function getPlaceLabel(): string
{
return $this->placeLabel;
}
public function getPlaceVisible(): int
{
return $this->placeVisible;
}
public function getReasonsLabel(): string
{
return $this->reasonsLabel;
@@ -688,6 +688,20 @@ class ActivityType
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
{
$this->reasonsLabel = $reasonsLabel;

View File

@@ -1,77 +0,0 @@
<?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,7 +25,6 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
use function count;

View File

@@ -27,7 +27,6 @@ use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
use function count;
use function in_array;
@@ -190,9 +189,7 @@ class ListActivity implements ListInterface
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
if (!array_key_exists('fields', $data)) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,45 +0,0 @@
<?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\Notification;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Notification\NotificationHandlerInterface;
final class ActivityNotificationHandler implements NotificationHandlerInterface
{
private ActivityRepository $activityRepository;
public function __construct(ActivityRepository $activityRepository)
{
$this->activityRepository = $activityRepository;
}
public function getTemplate(Notification $notification, array $options = []): string
{
return '@ChillActivity/Activity/showInNotification.html.twig';
}
public function getTemplateData(Notification $notification, array $options = []): array
{
return [
'notification' => $notification,
'activity' => $this->activityRepository->find($notification->getRelatedEntityId()),
];
}
public function supports(Notification $notification, array $options = []): bool
{
return $notification->getRelatedEntityClass() === Activity::class;
}
}

View File

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

View File

@@ -22,7 +22,6 @@ use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Security;
use function count;
use function in_array;
@@ -168,9 +167,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
$reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center);
// we get the ids for those scopes
$reachablesScopesId = array_map(
static function (Scope $scope) {
return $scope->getId();
},
static function (Scope $scope) { return $scope->getId(); },
$reachableScopes
);

View File

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

View File

@@ -9,9 +9,8 @@ div.new-activity-select-type {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
justify-content: center;
gap: 12px;
margin-bottom: 30px;
div.bloc {
width: 200px;
@@ -25,31 +24,30 @@ div.new-activity-select-type {
}
//// ACTIVITY LIST PAGE
// precise dashboard specific details
// precise badge-title specific details
p.date-label {
display: inline-block;
margin: 0 0.5em 0 0;
font-weight: 700;
font-size: 18pt;
}
div.dashboard,
h4.badge-title,
h3.badge-title,
h2.badge-title {
ul.list-content {
font-size: 70%;
list-style-type: none;
padding-left: 0;
margin: 0;
li {
margin-bottom: 0.2em;
// exception: change bg color for action badges above dashboard
.bg-light {
background-color: $chill-light-gray !important;
}
}
}
div.duration {
font-size: smaller;
padding-left: 1em;
margin-top: 1em;
}
ul.list-content {
font-size: 70%;
list-style-type: none;
padding-left: 0;
margin: 0;
li {
margin-bottom: 0.2em;
// exception: change bg color for action badges above badge-title
.bg-light {
background-color: $chill-light-gray !important;
}
}
}
}
div.main {
padding: 1em;
}
//// ACTIVITY SHOW AND FORM PAGES

View File

@@ -11,7 +11,7 @@ import Location from './components/Location.vue';
export default {
name: "App",
props: ['hasSocialIssues', 'hasLocation', 'hasPerson'],
props: ['hasSocialIssues', 'hasLocation', 'hasPerson'],
components: {
ConcernedGroups,
SocialIssuesAcc,

View File

@@ -17,14 +17,6 @@ const getLocations = () => fetchResults('/api/1.0/main/location.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
* @param {string} entity - can be "person" or "thirdparty"
@@ -56,6 +48,5 @@ export {
getLocations,
getLocationTypes,
getLocationTypeByDefaultFor,
postLocation,
getUserCurrentLocation
postLocation
};

View File

@@ -1,48 +1,45 @@
<template>
<teleport to="#add-persons" v-if="isComponentVisible">
<teleport to="#add-persons" v-if="isComponentVisible">
<div class="flex-bloc concerned-groups" :class="getContext">
<persons-bloc
v-for="bloc in contextPersonsBlocs"
v-bind:key="bloc.key"
v-bind:bloc="bloc"
v-bind:blocWidth="getBlocWidth"
v-bind:setPersonsInBloc="setPersonsInBloc">
</persons-bloc>
</div>
<div v-if="getContext === 'accompanyingCourse' && suggestedEntities.length > 0">
<ul class="list-suggest add-items inline">
<li v-for="(p, i) in suggestedEntities" @click="addSuggestedEntity(p)" :key="`suggestedEntities-${i}`">
<person-text v-if="p.type === 'person'" :person="p"></person-text>
<span v-else>{{ p.text }}</span>
</li>
</ul>
</div>
<div class="flex-bloc concerned-groups" :class="getContext">
<persons-bloc
v-for="bloc in contextPersonsBlocs"
v-bind:key="bloc.key"
v-bind:bloc="bloc"
v-bind:blocWidth="getBlocWidth"
v-bind:setPersonsInBloc="setPersonsInBloc">
</persons-bloc>
</div>
<div v-if="getContext === 'accompanyingCourse' && suggestedEntities.length > 0">
<ul class="list-suggest add-items">
<li v-for="p in suggestedEntities" @click="addSuggestedEntity(p)">
<span>{{ p.text }}</span>
</li>
</ul>
</div>
<add-persons
buttonTitle="activity.add_persons"
modalTitle="activity.add_persons"
v-bind:key="addPersons.key"
v-bind:options="addPersonsOptions"
@addNewPersons="addNewPersons"
ref="addPersons">
</add-persons>
<add-persons
buttonTitle="activity.add_persons"
modalTitle="activity.add_persons"
v-bind:key="addPersons.key"
v-bind:options="addPersonsOptions"
@addNewPersons="addNewPersons"
ref="addPersons">
</add-persons>
</teleport>
</teleport>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import PersonsBloc from './ConcernedGroups/PersonsBloc.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
export default {
name: "ConcernedGroups",
components: {
AddPersons,
PersonsBloc,
PersonText
PersonsBloc
},
data() {
return {

View File

@@ -1,29 +1,22 @@
<template>
<li>
<span :title="person.text">
<span class="chill_denomination" @click.prevent="$emit('remove', person)">
<person-text :person="person" :isCut="true"></person-text>
</span>
<span class="chill_denomination">{{ textCutted }}</span>
<a @click.prevent="$emit('remove', person)"></a>
</span>
</li>
</template>
<script>
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
export default {
name: "PersonBadge",
props: ['person'],
components: {
PersonText
computed: {
textCutted() {
let more = (this.person.text.length > 15) ?'…' : '';
return this.person.text.slice(0,15) + more;
}
},
// computed: {
// textCutted() {
// let more = (this.person.text.length > 15) ?'…' : '';
// return this.person.text.slice(0,15) + more;
// }
// },
emits: ['remove'],
}
</script>

View File

@@ -15,16 +15,14 @@
:searchable="true"
:placeholder="$t('activity.choose_location')"
:custom-label="customLabel"
:select-label="$t('multiselect.select_label')"
:deselect-label="$t('multiselect.deselect_label')"
:selected-label="$t('multiselect.selected_label')"
:options="availableLocations"
:options="locations"
group-values="locations"
group-label="locationGroup"
v-model="location"
>
</VueMultiselect>
<new-location v-bind:availableLocations="availableLocations"></new-location>
<new-location v-bind:locations="locations"></new-location>
</div>
</div>
</teleport>
@@ -34,6 +32,7 @@
import { mapState, mapGetters } from "vuex";
import VueMultiselect from "vue-multiselect";
import NewLocation from "./Location/NewLocation.vue";
import { getLocations, getLocationTypeByDefaultFor } from "../api.js";
export default {
name: "Location",
@@ -41,8 +40,13 @@ export default {
NewLocation,
VueMultiselect,
},
data() {
return {
locations: [],
};
},
computed: {
...mapState(["activity", "availableLocations"]),
...mapState(["activity"]),
...mapGetters(["suggestedEntities"]),
location: {
get() {
@@ -53,6 +57,53 @@ 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: {
labelAccompanyingCourseLocation(value) {
return `${value.address.text} (${value.locationType.title.fr})`
@@ -66,6 +117,58 @@ export default {
: 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>

View File

@@ -18,6 +18,15 @@
</template>
<template v-slot:body>
<form>
<div class="form-floating mb-3">
<p v-if="errors.length">
<b>{{ $t('activity.errors') }}</b>
<ul>
<li v-for="error in errors" :key="error">{{ error }}</li>
</ul>
</p>
</div>
<div class="form-floating mb-3">
<select class="form-select form-select-lg" id="type" required v-model="selectType">
<option selected disabled value="">{{ $t('activity.choose_location_type') }}</option>
@@ -53,12 +62,6 @@
<input class="form-control form-control-lg" id="email" v-model="inputEmail" placeholder />
<label for="email">{{ $t('activity.location_fields.email') }}</label>
</div>
<div class="alert alert-warning" v-if="errors.length">
<ul>
<li v-for="(e, i) in errors" :key="i">{{ e }}</li>
</ul>
</div>
</form>
</template>
<template v-slot:footer>
@@ -78,8 +81,7 @@
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import { mapState } from "vuex";
import { getLocationTypes } from "../../api";
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import { getLocationTypes, postLocation } from "../../api";
export default {
name: "NewLocation",
@@ -87,7 +89,7 @@ export default {
Modal,
AddAddress,
},
props: ['availableLocations'],
props: ['locations'],
data() {
return {
errors: [],
@@ -221,6 +223,7 @@ export default {
},
saveNewLocation() {
if (this.checkForm()) {
console.log('saveNewLocation', this.selected);
let body = {
type: 'location',
name: this.selected.name,
@@ -239,28 +242,23 @@ export default {
}
});
}
makeFetch('POST', '/api/1.0/main/location.json', body)
.then(response => {
this.$store.dispatch('addAvailableLocationGroup', {
locationGroup: 'Localisations nouvellement créées',
locations: [response]
});
this.$store.dispatch('updateLocation', response);
this.modal.showModal = false;
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.errors.push(v);
}
} else {
this.errors.push('An error occurred');
postLocation(body)
.then(
location => new Promise(resolve => {
this.locations.push(location);
this.$store.dispatch('updateLocation', location);
resolve();
this.modal.showModal = false;
})
).catch(
err => {
this.errors.push(err.message);
}
})
);
};
},
submitNewAddress(payload) {
console.log('submitNewAddress', payload);
this.selected.addressId = payload.addressId;
this.addAddress.context.addressId = payload.addressId;
this.addAddress.context.edit = true;

View File

@@ -9,9 +9,9 @@
<check-social-issue
v-for="issue in socialIssuesList"
:key="issue.id"
:issue="issue"
:selection="socialIssuesSelected"
v-bind:key="issue.id"
v-bind:issue="issue"
v-bind:selection="socialIssuesSelected"
@updateSelected="updateIssuesSelected">
</check-social-issue>
@@ -21,18 +21,18 @@
label="text"
track-by="id"
open-direction="bottom"
:close-on-select="true"
:preserve-search="false"
:reset-after="true"
:hide-selected="true"
:taggable="false"
:multiple="false"
:searchable="true"
:allow-empty="true"
:show-labels="false"
:loading="issueIsLoading"
:placeholder="$t('activity.choose_other_social_issue')"
:options="socialIssuesOther"
v-bind:close-on-select="true"
v-bind:preserve-search="false"
v-bind:reset-after="true"
v-bind:hide-selected="true"
v-bind:taggable="false"
v-bind:multiple="false"
v-bind:searchable="true"
v-bind:allow-empty="true"
v-bind:show-labels="false"
v-bind:loading="issueIsLoading"
v-bind:placeholder="$t('activity.choose_other_social_issue')"
v-bind:options="socialIssuesOther"
@select="addIssueInList">
</VueMultiselect>
</div>
@@ -58,9 +58,9 @@
<check-social-action
v-if="socialIssuesSelected.length || socialActionsSelected.length"
v-for="action in socialActionsList"
:key="action.id"
:action="action"
:selection="socialActionsSelected"
v-bind:key="action.id"
v-bind:action="action"
v-bind:selection="socialActionsSelected"
@updateSelected="updateActionsSelected">
</check-social-action>
</template>

View File

@@ -1,5 +1,4 @@
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n'
import { multiSelectMessages } from 'ChillMainAssets/vuejs/_js/i18n'
const activityMessages = {
fr: {
@@ -34,11 +33,12 @@ const activityMessages = {
},
create_address: 'Créer une adresse',
edit_address: "Modifier l'adresse"
}
}
}
Object.assign(activityMessages.fr, personMessages.fr, multiSelectMessages.fr);
Object.assign(activityMessages.fr, personMessages.fr);
export {
activityMessages

View File

@@ -12,11 +12,7 @@ const hasLocation = document.querySelector('#location') !== null;
const hasPerson = document.querySelector('#add-persons') !== null;
const app = createApp({
template: `<app
:hasSocialIssues="hasSocialIssues"
:hasLocation="hasLocation"
:hasPerson="hasPerson"
></app>`,
template: `<app :hasSocialIssues="hasSocialIssues", :hasLocation="hasLocation", :hasPerson="hasPerson"></app>`,
data() {
return {
hasSocialIssues,

View File

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

View File

@@ -1,123 +0,0 @@
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,8 +18,7 @@ use Symfony\Component\HttpFoundation\Request;
// 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.
if (
isset($_SERVER['HTTP_CLIENT_IP'])
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1'], true) || \PHP_SAPI === 'cli-server')
) {

View File

@@ -1,170 +0,0 @@
{% set t = activity.type %}
<div class="item-bloc activity-item{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
<div class="item-row">
<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 class="item-row column separator">
<div class="wrap-list">
{% if activity.location and t.locationVisible %}
<div class="wl-row">
<div class="wl-col title"><h3>{{ 'location'|trans }}</h3></div>
<div class="wl-col list">
<p class="wl-item">
{{ activity.location.name }}
<span>({{ activity.location.locationType.title|localize_translatable_string }})</span>
</p>
</div>
</div>
{% endif %}
{% if activity.attendee and t.attendeeVisible %}
<div class="wl-row">
<div class="wl-col title"><h3>{{ 'Attendee'|trans }}</h3></div>
<div class="wl-col list">
<p class="wl-item">
{{ activity.attendee.name|localize_translatable_string }}
</p>
</div>
</div>
{% 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|chill_entity_render_string|capitalize }}
</p>
</div>
</div>
{% endif %}
</div>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
'context': context,
'render': 'wrap-list',
'entity': activity,
'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 class="item-row separator">
<div class="item-col item-meta">
{% set notif_counter = chill_count_notifications('Chill\\ActivityBundle\\Entity\\Activity', activity.id) %}
{% if notif_counter.total > 0 %}
{{ chill_counter_notifications('Chill\\ActivityBundle\\Entity\\Activity', activity.id) }}
{% endif %}
</div>
<div class="item-col">
<ul class="record_actions">
{{ recordAction }}
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,110 @@
<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,16 +3,6 @@
{{ path(pathname, parms) }}
{% endmacro %}
{% macro insert_onthefly(type, entity, parent = null) %}
{% 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,
isDead: entity.deathdate is defined and entity.deathdate is not null,
parent: parent
} %}
{% endmacro %}
{% macro computeWidth(nbBlocks) %}
{{ 'flex-basis: ' ~ (100 / nbBlocks)|round(1) ~ '%;' }}
{% endmacro %}
@@ -23,7 +13,6 @@
{% set blocks = blocks|merge([{
'title': 'Others persons'|trans,
'items': entity.persons,
'type': 'person',
'path' : 'chill_person_view',
'key' : 'person_id'
}]) %}
@@ -31,13 +20,11 @@
{% set blocks = blocks|merge([{
'title': 'Persons in accompanying course'|trans,
'items': entity.personsAssociated,
'type': 'person',
'path' : 'chill_person_view',
'key' : 'person_id'
},{
'title': 'Third persons'|trans,
'items': entity.personsNotAssociated,
'type': 'person',
'path' : 'chill_person_view',
'key' : 'person_id',
}]) %}
@@ -47,7 +34,6 @@
{% set blocks = blocks|merge([{
'title': 'Third parties'|trans,
'items': entity.thirdParties,
'type': 'thirdparty',
'path' : 'chill_crud_3party_3party_view',
'key' : 'id',
}]) %}
@@ -56,12 +42,11 @@
{% set blocks = blocks|merge([{
'title': 'Users concerned'|trans,
'items': entity.users,
'type': 'user',
'key' : 'id',
}]) %}
{% endif %}
{% if (render == 'bloc') %}
{% if (with_display == 'bloc') %}
<div class="{{ context }} flex-bloc concerned-groups">
{% for bloc in blocks %}
@@ -74,12 +59,22 @@
<ul class="list-content">
{% for item in bloc.items %}
<li>
{% if bloc.type == 'user' %}
<span class="badge-user">
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
{% if bloc.path is defined %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
</a>
{% else %}
{{ _self.insert_onthefly(bloc.type, item) }}
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
{% endif %}
</li>
{% endfor %}
@@ -92,7 +87,7 @@
</div>
{% endif %}
{% if (render == 'row') %}
{% if (with_display == 'row') %}
<div class="concerned-groups">
{% for bloc in blocks %}
<div class="group">
@@ -101,12 +96,20 @@
<ul class="list-content">
{% for item in bloc.items %}
<li>
{% if bloc.type == 'user' %}
<span class="badge-user">
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
{% if bloc.path is defined %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</span>
</a>
{% else %}
{{ _self.insert_onthefly(bloc.type, item) }}
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
{% endif %}
</li>
{% endfor %}
@@ -117,24 +120,30 @@
</div>
{% endif %}
{% if (render == 'wrap-list') %}
{% if (with_display == 'wrap-list') %}
<div class="concerned-groups wrap-list">
{% for bloc in blocks %}
<div class="wl-row">
{% if bloc.items|length > 0 %}
<div class="wl-col title">
<h3>{{ bloc.title }}</h3>
<h4>{{ bloc.title }}</h4>
</div>
<div class="wl-col list">
{% for item in bloc.items %}
<span class="wl-item">
{% if bloc.type == 'user' %}
<span class="badge-user">
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
</span>
<span class="wl-item {% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
{% if bloc.path is defined %}
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
</a>
{% else %}
{{ _self.insert_onthefly(bloc.type, item) }}
{{ item|chill_entity_render_box({
'render': 'raw',
'addAltNames': false
}) }}
{% endif %}
</span>

View File

@@ -1,12 +1,5 @@
<h1>
{{ "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>
<h1>{{ "Update activity"|trans }}</h1>
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2>
{{ form_start(edit_form) }}
{{ form_errors(edit_form) }}
@@ -44,7 +37,7 @@
{% endif %}
{%- if edit_form.persons is defined or edit_form.thirdParties is defined or edit_form.users is defined -%}
<h2 class="chill-blue">{{ 'Concerned groups'|trans }}</h2>
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
{%- if edit_form.persons is defined -%}
{{ form_widget(edit_form.persons) }}
@@ -60,7 +53,7 @@
{% endif %}
<h2 class="chill-blue">{{ 'Activity data'|trans }}</h2>
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
{%- if edit_form.date is defined -%}
{{ form_row(edit_form.date) }}
@@ -80,18 +73,19 @@
{% endif %}
{%- if edit_form.comment is defined -%}
{# TODO .. public and private #}
{{ form_row(edit_form.comment) }}
{% endif %}
{%- if edit_form.attendee is defined -%}
{{ form_row(edit_form.attendee) }}
{% endif %}
{%- if edit_form.documents is defined -%}
{{ form_row(edit_form.documents) }}
{% endif %}
<div data-docgen-template-picker="data-docgen-template-picker" data-entity-class="Chill\ActivityBundle\Entity\Activity" data-entity-id="{{ entity.id }}"></div>
{%- if edit_form.attendee is defined -%}
{{ form_row(edit_form.attendee) }}
{% endif %}
{# TODO .. status #}
{% set person_id = null %}
{% if entity.person %}
@@ -103,16 +97,16 @@
{% set accompanying_course_id = accompanyingCourse.id %}
{% endif %}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-cancel">
{{ 'Cancel'|trans }}
</a>
</li>
<li>
<button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button>
</li>
</ul>
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-cancel">
{{ 'Cancel'|trans }}
</a>
</li>
<li>
<button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button>
</li>
</ul>
{{ form_end(edit_form) }}
{# {{ form(delete_form) }} #}

View File

@@ -15,7 +15,7 @@
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_async_upload') }}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
@@ -24,12 +24,10 @@
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{{ encore_entry_script_tags('mod_docgen_picktemplate') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{{ encore_entry_link_tags('mod_docgen_picktemplate') }}
{% endblock %}

View File

@@ -30,7 +30,7 @@
{% endblock %}
{% block js %}
{{ encore_entry_script_tags('mod_async_upload') }}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
@@ -39,11 +39,9 @@
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{{ encore_entry_script_tags('mod_docgen_picktemplate') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{{ encore_entry_link_tags('mod_docgen_picktemplate') }}
{% endblock %}

View File

@@ -1,65 +1,3 @@
{% macro recordAction(activity, context = null, person_id = null, accompanying_course_id = null) %}
{% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %}
{% if no_action is not defined or no_action == false %}
<li>
<a class="btn btn-misc" href="{{ chill_path_add_return_path('chill_main_notification_create', {
'entityClass': 'Chill\\ActivityBundle\\Entity\\Activity',
'entityId': activity.id
}) }}">
<i class="fa fa-paper-plane fa-fw"></i>
{{ 'notification.Notify'|trans }}</a>
</li>
{% endif %}
{% 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>
<a href="{{ path('chill_activity_activity_show', {'id': activity.id,
'person_id': person_id,
'accompanying_period_id': accompanying_course_id
}) }}"
class="btn btn-show"
title="{{ 'Show'|trans }}"></a>
</li>
{% if no_action is not defined or no_action == false %}
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
<li>
<a href="{{ path('chill_activity_activity_edit', {'id': activity.id,
'person_id': person_id,
'accompanying_period_id': accompanying_course_id
}) }}"
class="btn btn-update"
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 %}
{% endmacro %}
<div class="context-{{ context }}">
{% if activities|length == 0 %}
@@ -70,10 +8,56 @@
{% else %}
<div class="flex-table activity-list">
{% for activity in activities %}
{% include 'ChillActivityBundle:Activity:_list_item.html.twig' with {
'context': context,
'recordAction': _self.recordAction(activity, context, person_id, accompanying_course_id)
} %}
{% set t = activity.type %}
<div class="item-bloc">
<div class="item-row">
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %}
</div>
{% if activity.comment.comment is not empty
or activity.persons|length > 0
or activity.thirdParties|length > 0
or activity.users|length > 0
%}
<div class="main">
{% if activity.comment.comment is not empty %}
{{ activity.comment|chill_entity_render_box({
'disable_markdown': false,
'limit_lines': 3,
'metadata': false,
}) }}
{% endif %}
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
'context': context,
'with_display': 'row',
'entity': activity,
'badge_person': true
} %}
</div>
{% endif %}
<div class="item-row separator">
<div class="updatedBy"></div>
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-sm btn-show "></a>
</li>
{% if no_action is not defined or no_action == false %}
<li>
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-sm btn-update "></a>
</li>
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
class="btn btn-sm btn-delete "></a>
</li>
{% endif %}
</ul>
</div>
</div>
{% endfor %}
</div>
{% endif %}

View File

@@ -4,17 +4,6 @@
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{% endblock %}
{% block content %}
{% set person_id = null %}
@@ -34,8 +23,8 @@
{% if is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) %}
<ul class="record_actions sticky-form-buttons">
<li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
class="btn btn-create">{{ 'Create'|trans }}
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
{{ 'Create'|trans }}
</a>
</li>
</ul>

View File

@@ -20,16 +20,6 @@
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{% endblock %}
{% block personcontent %}
{% set person_id = null %}

View File

@@ -3,88 +3,10 @@
{% set t = activity.type %}
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="dashboard-link" title="{{ 'Show the activity'|trans }}">
class="badge-link" title="{{ 'Show the activity'|trans }}">
<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({'addAgeBadge': true}) }}</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>
{% include '@ChillActivity/Activity/activity-badge-title.html.twig' %}
</a>
{% endfor %}
</div>

View File

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

View File

@@ -14,7 +14,7 @@
{% endblock %}
{% block js %}
{{ encore_entry_script_tags('mod_async_upload') }}
{{ encore_entry_link_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',

View File

@@ -25,7 +25,7 @@
'activityData': activityData
}) }}">
<div class="btn btn-primary">
<div class="bloc btn btn-primary btn-lg btn-block">
{{ activityType.name|localize_translatable_string }}
</div>
</a>

View File

@@ -1,188 +1,128 @@
{%- set t = entity.type -%}
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
<h1>{{ "Activity"|trans }}</h1>
<h1>
{{ "Activity"|trans }}
{%- if t.emergencyVisible and entity.emergency -%}
<span class="badge bg-secondary">
{{- 'Emergency'|trans -}}
</span>
{%- endif -%}
</h1>
<div class="flex-table">
<div class="item-bloc">
<dl class="chill_view_data">
<div class="item-row">
<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">{{ 'by'|trans|capitalize }}</dt>
<dd>{{ entity.user }}</dd>
<div class="item-row separator">
<dl class="chill_view_data">
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
<dd>{{ entity.user|chill_entity_render_box }}</dd>
<dt class="inline">{{ 'Type'|trans }}</dt>
<dd>{{ entity.type.name | localize_translatable_string }}</dd>
{%- if entity.scope -%}
<dt class="inline">{{ 'Scope'|trans }}</dt>
<dd>
<span class="scope">{{ entity.scope.name|localize_translatable_string }}</span>
</dd>
{% endif %}
{% if t.socialIssuesVisible %}
<dt class="inline">{{ 'Social issues'|trans }}</dt>
<dd>
{% if entity.socialIssues|length == 0 %}
<p class="chill-no-data-statement">{{ 'No social issues associated'|trans }}</p>
{% else %}
{% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.socialActionsVisible %}
<dt class="inline">{{ 'Social actions'|trans }}</dt>
<dd>
{% if entity.socialActions|length == 0 %}
<span class="chill-no-data-statement">{{ 'No social actions associated'|trans }}</span>
{% else %}
{% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.reasonsVisible %}
<dt class="inline">{{ 'Reasons'|trans }}</dt>
<dd>
{%- if entity.reasons is empty -%}
<span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span>
{%- else -%}
{% for r in entity.reasons %}{{ r|chill_entity_render_box }}{% endfor %}
{%- endif -%}
</dd>
{% endif %}
</dl>
</div>
</div>
</div>
<h2 class="chill-blue">{{ 'Concerned groups'|trans }}</h2>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
'context': context,
'render': 'bloc',
'badge_person': true
} %}
<h2 class="chill-blue">{{ 'Activity data'|trans }}</h2>
<div class="flex-table">
<div class="item-bloc">
<dl class="chill_view_data">
<dt class="inline">{{ 'Date'|trans }}</dt>
<dd>{{ entity.date|format_date('long') }}</dd>
{% if t.locationVisible %}
<dt class="inline">{{ 'Activity location'|trans }}</dt>
<dd>
{% if entity.location is not null %}
<p>
{{ entity.location.name }}
<span>({{ entity.location.locationType.title|localize_translatable_string }})</span>
</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 %}
{% if t.durationTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Duration Time'|trans }}</dt>
<dd>
{% if entity.durationTime is not null %}
{{ entity.durationTime|date('H:i') }}
{% else %}
<span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
{% endif %}
</dd>
{% endif %}
{% if t.travelTimeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Travel time'|trans }}</dt>
<dd>
{% if entity.travelTime is not null %}
{{ entity.travelTime|date('H:i') }}
{% else %}
<span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
{% endif %}
</dd>
{% endif %}
{% if t.commentVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'activity.comment'|trans }}</dt>
<dd>
{%- if entity.comment.empty -%}
<span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span>
{%- else -%}
{{ entity.comment|chill_entity_render_box }}
{%- endif -%}
</dd>
{% endif %}
{% if t.documentsVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Documents'|trans }}</dt>
<dd>
{% if entity.documents|length > 0 %}
<ul>
{% for d in entity.documents %}
<li>{{ m.download_button(d) }}</li>
{% endfor %}
</ul>
{% else %}
<span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span>
{% endif %}
</dd>
{% endif %}
{% if t.attendeeVisible and is_granted('CHILL_ACTIVITY_SEE_DETAILS', entity) %}
<dt class="inline">{{ 'Attendee'|trans }}</dt>
<dd>
{% if entity.attendee is not null %}
{{ entity.attendee.name|localize_translatable_string }}
{% else %}
<span class="chill-no-data-statement">{{ 'None'|trans|capitalize }}</span>
{% endif %}
</dd>
{% endif %}
</dl>
</div>
</div>
<div class="notification notification-list">
{% set notifications = chill_list_notifications('Chill\\ActivityBundle\\Entity\\Activity', entity.id) %}
{% if notifications is not empty %}
{{ notifications|raw }}
{%- if entity.scope -%}
<dt class="inline">{{ 'Scope'|trans }}</dt>
<dd><span class="scope">{{ entity.scope.name|localize_translatable_string }}</span></dd>
{% endif %}
</div>
{% if t.socialIssuesVisible %}
<dt class="inline">{{ 'Social issues'|trans }}</dt>
<dd>
{% if entity.socialIssues|length == 0 %}
<p class="chill-no-data-statement">{{ 'No social issues associated'|trans }}</p>
{% else %}
{% for si in entity.socialIssues %}{{ si|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.socialActionsVisible %}
<dt class="inline">{{ 'Social actions'|trans }}</dt>
<dd>
{% if entity.socialActions|length == 0 %}
<p class="chill-no-data-statement">{{ 'No social actions associated'|trans }}</p>
{% else %}
{% for sa in entity.socialActions %}{{ sa|chill_entity_render_box }}{% endfor %}
{% endif %}
</dd>
{% endif %}
{% if t.reasonsVisible %}
<dt class="inline">{{ 'Reasons'|trans }}</dt>
{%- if entity.reasons is empty -%}
<dd><span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span></dd>
{%- else -%}
<dd>{% for r in entity.reasons %}{{ r|chill_entity_render_box }} {% endfor %}</dd>
{%- endif -%}
{% endif %}
<h2 class="chill-red">{{ 'Concerned groups'|trans }}</h2>
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc', 'badge_person': 'true' } %}
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
<dt class="inline">{{ 'Date'|trans }}</dt>
<dd>{{ entity.date|format_date('long') }}</dd>
{% if t.locationVisible %}
<dt class="inline">{{ 'Activity location'|trans }}</dt>
<dd>
{% if entity.location is not null %}
<p>
{{ entity.location.name }}
<span> ({{ entity.location.locationType.title|localize_translatable_string }})</span>
</p>
{{ entity.location.address|chill_entity_render_box }}
{% else %}
<span class="chill-no-data-statement">{{ 'No address given'|trans }}</span>
{% endif %}
</dd>
{% endif %}
{% if t.durationTimeVisible %}
<dt class="inline">{{ 'Duration Time'|trans }}</dt>
<dd>{% if entity.durationTime is not null %}
{{ entity.durationTime|date('H:i') }}
{% else %}
{{ 'None'|trans|capitalize }}
{% endif %}
</dd>
{% endif %}
{% if t.travelTimeVisible %}
<dt class="inline">{{ 'Travel time'|trans }}</dt>
<dd>{% if entity.travelTime is not null %}
{{ entity.travelTime|date('H:i') }}
{% else %}
{{ 'None'|trans|capitalize }}
{% endif %}
</dd>
{% endif %}
{% if t.commentVisible %}
<dt class="inline">{{ 'activity.comment'|trans }}</dt>
{%- if entity.comment.empty -%}
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd>
{%- else -%}
<dd>{{ entity.comment|chill_entity_render_box }}</dd>
{%- endif -%}
{% endif %}
{% if t.documentsVisible and entity.documents|length > 0 %}
<dt>{{ 'Documents'|trans }}</dt>
<dd>
<ul>
{% for d in entity.documents %}
<li>{{ m.download_button(d) }}</li>
{% endfor %}
</ul>
</dd>
{% endif %}
{% if t.attendeeVisible %}
<dt class="inline">{{ 'Attendee'|trans }}</dt>
<dd>{% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}</dd>
{% endif %}
</dl>
{% set person_id = null %}
{% if person %}
@@ -201,20 +141,22 @@
</a>
</li>
<li>
<a class="btn btn-notify" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\ActivityBundle\\Entity\\Activity', 'entityId': entity.id}) }}">
{{ 'notification.Notify'|trans }}
<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 }}
</a>
</li>
{% if is_granted('CHILL_ACTIVITY_UPDATE', entity) %}
<li>
<a href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-update">{{ 'Edit'|trans }}</a>
</li>
{% endif %}
{# TODO
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
#}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
class="btn btn-delete" title="{{ 'Delete'|trans }}"></a>
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete">
{{ 'Delete'|trans }}
</a>
</li>
{#
{% endif %}
#}
</ul>

View File

@@ -4,26 +4,12 @@
{% block title 'Show the activity'|trans %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_script_tags('mod_async_upload') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{% endblock %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
{% block content -%}
<div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
</div>
{% endblock content %}
{% block block_post_menu %}
<div class="post-menu pt-4"></div>
{% endblock %}

View File

@@ -1,27 +1,2 @@
{% macro recordAction(activity) %}
<li>
<a href="{{ path('chill_activity_activity_show', {'id': activity.id }) }}"
class="btn btn-show" title="{{ 'Show the activity'|trans }}"></a>
</li>
{% endmacro %}
{% if activity is not null %}
<div class="flex-table">
{% if is_granted('CHILL_ACTIVITY_SEE', activity) %}
{% include 'ChillActivityBundle:Activity:_list_item.html.twig' with {
'recordAction': _self.recordAction(activity),
'context': 'accompanyingCourse',
'itemBlocClass': 'bg-chill-llight-gray'
} %}
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'This is the minimal activity data'|trans ~ ': ' ~ activity.id }}<br>
{{ 'you are not allowed to see it details'|trans }}
</div>
{% endif %}
</div>
{% else %}
<div class="alert alert-warning border-warning border-1">
{{ 'You get notified of an activity which does not exists any more'|trans }}
</div>
{% endif %}
<a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId }) }}">Go to Activity</a>

View File

@@ -4,39 +4,12 @@
{% block title 'Show the activity'|trans %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{% endblock %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
{% block personcontent -%}
<div class="activity-show">
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
</div>
{% endblock personcontent %}
{% block block_post_menu %}
<div class="post-menu pt-4">
<div class="d-grid gap-2">
<a class="btn btn-notify" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\ActivityBundle\\Entity\\Activity', 'entityId': entity.id}) }}">
{{ 'notification.Notify'|trans }}
</a>
</div>
{% set notifications = chill_list_notifications('Chill\\ActivityBundle\\Entity\\Activity', entity.id) %}
{% if notifications is not empty %}
{{ notifications|raw }}
{% endif %}
</div>
{% endblock %}

View File

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

View File

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

View File

@@ -1,220 +0,0 @@
<?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\Service\DocGenerator;
use Chill\ActivityBundle\Entity\Activity;
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface;
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
use Chill\DocGeneratorBundle\Context\Exception\UnexpectedTypeException;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\DocGeneratorBundle\Service\Context\BaseContextData;
use Chill\DocStoreBundle\Entity\Document;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\DocumentCategoryRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Templating\Entity\PersonRender;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class ActivityContext implements
DocGeneratorContextWithAdminFormInterface,
DocGeneratorContextWithPublicFormInterface
{
private BaseContextData $baseContextData;
private DocumentCategoryRepository $documentCategoryRepository;
private EntityManagerInterface $em;
private NormalizerInterface $normalizer;
private PersonRender $personRender;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatorInterface $translator;
public function __construct(
DocumentCategoryRepository $documentCategoryRepository,
NormalizerInterface $normalizer,
TranslatableStringHelperInterface $translatableStringHelper,
EntityManagerInterface $em,
PersonRender $personRender,
TranslatorInterface $translator,
BaseContextData $baseContextData
) {
$this->documentCategoryRepository = $documentCategoryRepository;
$this->normalizer = $normalizer;
$this->translatableStringHelper = $translatableStringHelper;
$this->em = $em;
$this->personRender = $personRender;
$this->translator = $translator;
$this->baseContextData = $baseContextData;
}
public function adminFormReverseTransform(array $data): array
{
return $data;
}
public function adminFormTransform(array $data): array
{
return [
'mainPerson' => $data['mainPerson'] ?? false,
'mainPersonLabel' => $data['mainPersonLabel'] ?? $this->translator->trans('docgen.Main person'),
'person1' => $data['person1'] ?? false,
'person1Label' => $data['person1Label'] ?? $this->translator->trans('docgen.person 1'),
'person2' => $data['person2'] ?? false,
'person2Label' => $data['person2Label'] ?? $this->translator->trans('docgen.person 2'),
];
}
public function buildAdminForm(FormBuilderInterface $builder): void
{
$builder
->add('mainPerson', CheckboxType::class, [
'required' => false,
'label' => 'docgen.Ask for main person',
])
->add('mainPersonLabel', TextType::class, [
'label' => 'main person label',
'required' => true,
])
->add('person1', CheckboxType::class, [
'required' => false,
'label' => 'docgen.Ask for person 1',
])
->add('person1Label', TextType::class, [
'label' => 'person 1 label',
'required' => true,
])
->add('person2', CheckboxType::class, [
'required' => false,
'label' => 'docgen.Ask for person 2',
])
->add('person2Label', TextType::class, [
'label' => 'person 2 label',
'required' => true,
]);
}
/**
* @param Activity $entity
*/
public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void
{
$options = $template->getOptions();
$persons = $entity->getPersons();
foreach (['mainPerson', 'person1', 'person2'] as $key) {
if ($options[$key] ?? false) {
$builder->add($key, EntityType::class, [
'class' => Person::class,
'choices' => $persons,
'choice_label' => function (Person $p) {
return $this->personRender->renderString($p, []);
},
'multiple' => false,
'expanded' => true,
'label' => $options[$key . 'Label'],
]);
}
}
}
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
{
if (!$entity instanceof Activity) {
throw new UnexpectedTypeException($entity, Activity::class);
}
$options = $template->getOptions();
$data = [];
$data = array_merge($data, $this->baseContextData->getData());
$data['activity'] = $this->normalizer->normalize($entity, 'docgen', ['docgen:expects' => Activity::class, 'groups' => 'docgen:read']);
$data['course'] = $this->normalizer->normalize($entity->getAccompanyingPeriod(), 'docgen', ['docgen:expects' => AccompanyingPeriod::class, 'groups' => 'docgen:read']);
$data['person'] = $this->normalizer->normalize($entity->getPerson(), 'docgen', ['docgen:expects' => Person::class, 'groups' => 'docgen:read']);
foreach (['mainPerson', 'person1', 'person2'] as $k) {
if ($options[$k]) {
$data[$k] = $this->normalizer->normalize($contextGenerationData[$k], 'docgen', [
'docgen:expects' => Person::class,
'groups' => 'docgen:read',
'docgen:person:with-household' => true,
'docgen:person:with-relations' => true,
]);
}
}
return $data;
}
public function getDescription(): string
{
return 'docgen.A basic context for activity';
}
public function getEntityClass(): string
{
return Activity::class;
}
public function getFormData(DocGeneratorTemplate $template, $entity): array
{
return [
'activity' => $entity,
];
}
public static function getKey(): string
{
return self::class;
}
public function getName(): string
{
return 'docgen.Activity basic';
}
public function hasAdminForm(): bool
{
return true;
}
public function hasPublicForm(DocGeneratorTemplate $template, $entity): bool
{
$options = $template->getOptions();
return $options['mainPerson'] || $options['person1'] || $options['person2'];
}
/**
* @param Activity $entity
*/
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
{
$doc = new StoredObject();
// TODO push document to remote
$this->em->persist($doc);
$entity->addDocument($doc);
}
}

View File

@@ -66,7 +66,7 @@ final class ActivityReasonCategoryControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@@ -66,7 +66,7 @@ final class ActivityReasonControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@@ -66,7 +66,7 @@ final class ActivityTypeControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
}
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -29,13 +29,9 @@ use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
final class ActivityVoterTest extends KernelTestCase
{
use PrepareActivityTrait;
use PrepareCenterTrait;
use PreparePersonTrait;
use PrepareScopeTrait;
use PrepareUserTrait;
/**
@@ -48,7 +44,7 @@ final class ActivityVoterTest extends KernelTestCase
*/
protected $voter;
protected function setUp(): void
public function setUp()
{
self::bootKernel();
$this->voter = self::$kernel->getContainer()

View File

@@ -24,7 +24,6 @@ use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
use function implode;
use function in_array;
use function strtr;

View File

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

View File

@@ -32,8 +32,3 @@ services:
autowire: true
autoconfigure: true
resource: '../Validator/Constraints/'
Chill\ActivityBundle\Service\DocGenerator\:
autowire: true
autoconfigure: true
resource: '../Service/DocGenerator/'

View File

@@ -1,15 +0,0 @@
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,7 +13,6 @@ namespace Chill\Migrations\Activity;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use function count;
/**

View File

@@ -1,34 +0,0 @@
<?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

@@ -76,7 +76,7 @@ activity:
Insert a document: Insérer un document
Remove a document: Supprimer le document
comment: Commentaire
No documents: Pas de documents
#timeline
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
@@ -146,8 +146,8 @@ User visible: Visibilité du champ Utilisateur
User label: Libellé du champ Utilisateur
Date visible: Visibilité du champ Date
Date label: Libellé du champ Date
Location visible: Visibilité du champ Lieu
Location label: Libellé du champ Lieu
Place visible: Visibilité du champ Lieu
Place label: Libellé du champ Lieu
Third parties visible: Visibilité du champ Tiers
Third parties label: Libellé du champ Tiers
Duration time visible: Visibilité du champ Durée
@@ -222,13 +222,3 @@ Aggregate by activity type: Aggréger par type d'activité
Aggregate by activity reason: Aggréger par sujet de l'activité
Last activities: Les dernières activités
See activity in accompanying course context: Voir l'activité dans le contexte du parcours d'accompagnement
You get notified of an activity which does not exists any more: Cette notification ne correspond pas à une activité valide.
you are not allowed to see it details: La notification fait référence à une activité à laquelle vous n'avez pas accès.
This is the minimal activity data: Activité n°
docgen:
Activity basic: Echange
A basic context for activity: Contexte pour les échanges

View File

@@ -20,4 +20,3 @@ For this type of activity, you must add at least one social action: Pour ce type
# admin
This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales"
The socialActionsVisible value is not compatible with the socialIssuesVisible value: Cette valeur du paramètre "Visibilité du champs Actions sociales" n'est pas compatible avec la valeur du paramètre "Visibilité du champs Problématiques sociales"

View File

@@ -32,8 +32,6 @@ final class AsideActivityController extends CRUDController
{
$asideActivity = new AsideActivity();
$asideActivity->setAgent($this->getUser());
$duration = $request->query->get('duration', '300');
$duration = DateTime::createFromFormat('U', $duration);
$asideActivity->setDuration($duration);

View File

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

View File

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

View File

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

View File

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

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