mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-13 02:04:58 +00:00
Compare commits
1 Commits
optimize_a
...
integratio
Author | SHA1 | Date | |
---|---|---|---|
57a9f52fa1 |
@@ -7,7 +7,6 @@ charset = utf-8
|
||||
end_of_line = LF
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 4
|
||||
|
||||
[*.{php,html,twig}]
|
||||
indent_style = space
|
||||
|
45
CHANGELOG.md
45
CHANGELOG.md
@@ -1,45 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to
|
||||
|
||||
* [Semantic Versioning](https://semver.org/spec/v2.0.0.html) for stable releases;
|
||||
* date versioning for test releases
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Address: zoom on postal code geometry + fix origin of manually entered postal code
|
||||
|
||||
* [Aside activity] Fixes for aside activity
|
||||
|
||||
* categories with child
|
||||
* fast creation buttons
|
||||
* add ordering for types
|
||||
|
||||
|
||||
## Test releases
|
||||
|
||||
### test release 2021-10-04
|
||||
|
||||
* [Household editor][UI] Update how household suggestion and addresses are picked;
|
||||
* [AddAddress] Handle address suggestion;
|
||||
* [CenterType][Create a person] when overriding the ACL rules, allow to show a PickCenterType
|
||||
when no centers are reachable by the default ACL.
|
||||
* [Household] Show comment event if no address are associated with the household;
|
||||
* [Person results] Add requestor into search results:
|
||||
|
||||
* a badge "requestor" is shown into search results;
|
||||
* periods where the person is only requestor (without participating) are also shown;
|
||||
|
||||
Issues:
|
||||
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/13
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/199
|
||||
* [Person form] "accept sms" not required:
|
||||
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/37
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/221
|
||||
* On-The-Fly modale works for showing, editing and creating person and thirdparty ;
|
||||
* AccompanyingCourse Resume page: list associated persons by household, see household when hover, and show on-the-fly modale when clicking on person ;
|
120
composer.json
120
composer.json
@@ -1,72 +1,12 @@
|
||||
{
|
||||
"name": "chill-project/chill-bundles",
|
||||
"license": "AGPL-3.0-only",
|
||||
"type": "library",
|
||||
"description": "Most used bundles for chill-project",
|
||||
"keywords": [
|
||||
"chill",
|
||||
"social worker"
|
||||
],
|
||||
"license": "AGPL-3.0-only",
|
||||
"require": {
|
||||
"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",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"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.*",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/swiftmailer-bundle": "^3.5",
|
||||
"symfony/templating": "4.*",
|
||||
"symfony/translation": "4.*",
|
||||
"symfony/twig-bundle": "^4.4",
|
||||
"symfony/validator": "4.*",
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"symfony/workflow": "4.*",
|
||||
"symfony/yaml": "4.*",
|
||||
"twig/extra-bundle": "^2.12 || ^3.0",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"twig/markdown-extra": "^3.3",
|
||||
"twig/twig": "^2.12 || ^3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.3",
|
||||
"fakerphp/faker": "^1.13",
|
||||
"nelmio/alice": "^3.8",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/dotenv": "^5.1",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"symfony/stopwatch": "^5.1",
|
||||
"symfony/var-dumper": "4.*",
|
||||
"symfony/web-profiler-bundle": "^5.0"
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin",
|
||||
"vendor-dir": "tests/app/vendor"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle",
|
||||
@@ -93,10 +33,68 @@
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"champs-libres/async-uploader-bundle": "dev-sf4",
|
||||
"champs-libres/wopi-bundle": "dev-master",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"graylog2/gelf-php": "^1.5",
|
||||
"symfony/form": "4.*",
|
||||
"symfony/twig-bundle": "^4.4",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0",
|
||||
"composer/package-versions-deprecated": "^1.10",
|
||||
"doctrine/doctrine-bundle": "^2.1",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"symfony/asset": "4.*",
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "4.*",
|
||||
"symfony/translation": "4.*",
|
||||
"symfony/validator": "4.*",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"symfony/yaml": "4.*",
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"knplabs/knp-menu": "^3.1",
|
||||
"knplabs/knp-menu-bundle": "^3.0",
|
||||
"symfony/templating": "4.*",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"symfony/workflow": "4.*",
|
||||
"symfony/expression-language": "4.*",
|
||||
"knplabs/knp-time-bundle": "^1.12",
|
||||
"symfony/intl": "4.*",
|
||||
"symfony/swiftmailer-bundle": "^3.5",
|
||||
"league/csv": "^9.7.1",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"symfony/browser-kit": "^5.2",
|
||||
"symfony/css-selector": "^5.2",
|
||||
"twig/markdown-extra": "^3.3",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/webpack-encore-bundle": "^1.11"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.13",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/dotenv": "^5.1",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.3",
|
||||
"symfony/stopwatch": "^5.1",
|
||||
"symfony/web-profiler-bundle": "^5.0",
|
||||
"symfony/var-dumper": "4.*",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"nelmio/alice": "^3.8"
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin"
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
<server name="APP_ENV" value="test" force="true" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
<server name="SHELL_VERBOSITY" value="-1" />
|
||||
</php>
|
||||
|
||||
@@ -31,12 +31,6 @@
|
||||
<!-- temporarily removed, the time to find a fix -->
|
||||
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
|
||||
</testsuite>
|
||||
<testsuite name="AsideActivityBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="CalendarBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<listeners>
|
||||
|
@@ -22,9 +22,6 @@
|
||||
|
||||
namespace Chill\ActivityBundle\Controller;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
@@ -39,7 +36,6 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Form\ActivityType;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@@ -57,16 +53,12 @@ class ActivityController extends AbstractController
|
||||
|
||||
protected SerializerInterface $serializer;
|
||||
|
||||
protected ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
|
||||
|
||||
public function __construct(
|
||||
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer
|
||||
) {
|
||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->logger = $logger;
|
||||
@@ -85,9 +77,13 @@ class ActivityController extends AbstractController
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($person instanceof Person) {
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByPerson($person, ActivityVoter::SEE, 0, null);
|
||||
$reachableScopes = $this->authorizationHelper
|
||||
->getReachableCircles($this->getUser(), new Role('CHILL_ACTIVITY_SEE'),
|
||||
$person->getCenter());
|
||||
|
||||
$activities = $em->getRepository(Activity::class)
|
||||
->findByPersonImplied($person, $reachableScopes)
|
||||
;
|
||||
|
||||
$event = new PrivacyEvent($person, array(
|
||||
'element_class' => Activity::class,
|
||||
@@ -97,10 +93,10 @@ class ActivityController extends AbstractController
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listPerson.html.twig';
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
|
||||
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE);
|
||||
$activities = $em->getRepository('ChillActivityBundle:Activity')->findBy(
|
||||
['accompanyingPeriod' => $accompanyingPeriod],
|
||||
['date' => 'DESC'],
|
||||
);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
}
|
||||
@@ -140,12 +136,6 @@ class ActivityController extends AbstractController
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
} else {
|
||||
$activityData = [];
|
||||
}
|
||||
|
||||
if ($view === null) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
@@ -154,7 +144,6 @@ class ActivityController extends AbstractController
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'data' => $data,
|
||||
'activityData' => $activityData
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -174,19 +163,10 @@ class ActivityController extends AbstractController
|
||||
$activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->find($activityType_id);
|
||||
|
||||
$activityData = null;
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
}
|
||||
|
||||
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType ||
|
||||
!$activityType->isActive()) {
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
|
||||
if (null !== $activityData) {
|
||||
$params['activityData'] = $activityData;
|
||||
}
|
||||
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
|
||||
}
|
||||
|
||||
@@ -204,50 +184,6 @@ class ActivityController extends AbstractController
|
||||
$entity->setType($activityType);
|
||||
$entity->setDate(new \DateTime('now'));
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
|
||||
if (array_key_exists('durationTime', $activityData)) {
|
||||
$durationTimeInMinutes = $activityData['durationTime'];
|
||||
$hours = floor($durationTimeInMinutes / 60);
|
||||
$minutes = $durationTimeInMinutes % 60;
|
||||
$duration = \DateTime::createFromFormat("H:i", $hours.':'.$minutes);
|
||||
if ($duration) {
|
||||
$entity->setDurationTime($duration);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('date', $activityData)) {
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
|
||||
if ($date) {
|
||||
$entity->setDate($date);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('personsId', $activityData)) {
|
||||
foreach($activityData['personsId'] as $personId){
|
||||
$concernedPerson = $em->getRepository(\Chill\PersonBundle\Entity\Person::class)->find($personId);
|
||||
$entity->addPerson($concernedPerson);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('professionalsId', $activityData)) {
|
||||
foreach($activityData['professionalsId'] as $professionalsId){
|
||||
$professional = $em->getRepository(\Chill\ThirdPartyBundle\Entity\ThirdParty::class)->find($professionalsId);
|
||||
$entity->addThirdParty($professional);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('comment', $activityData)) {
|
||||
$comment = new CommentEmbeddable();
|
||||
$comment->setComment($activityData['comment']);
|
||||
$comment->setUserId($this->getUser()->getid());
|
||||
$comment->setDate(new \DateTime('now'));
|
||||
$entity->setComment($comment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity);
|
||||
|
||||
@@ -265,7 +201,6 @@ class ActivityController extends AbstractController
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
|
||||
$params['id'] = $entity->getId();
|
||||
|
||||
return $this->redirectToRoute('chill_activity_activity_show', $params);
|
||||
@@ -303,7 +238,7 @@ class ActivityController extends AbstractController
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
}
|
||||
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
$entity->personsAssociated = $entity->getPersonsAssociated();
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
|
@@ -55,7 +55,6 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
|
||||
$loader->load('services/controller.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
$loader->load('services/templating.yaml');
|
||||
$loader->load('services/accompanyingPeriodConsistency.yaml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
|
@@ -23,7 +23,6 @@ namespace Chill\ActivityBundle\Entity;
|
||||
use Chill\DocStoreBundle\Entity\Document;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
@@ -61,7 +60,7 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
* path="scope")
|
||||
*/
|
||||
|
||||
class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
|
||||
class Activity implements HasCenterInterface, HasScopeInterface
|
||||
{
|
||||
const SENTRECEIVED_SENT = 'sent';
|
||||
const SENTRECEIVED_RECEIVED = 'received';
|
||||
@@ -418,7 +417,7 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
|
||||
return $this->persons;
|
||||
}
|
||||
|
||||
public function getPersonsAssociated(): array
|
||||
public function getPersonsAssociated(): array
|
||||
{
|
||||
if (null !== $this->accompanyingPeriod) {
|
||||
$personsAssociated = [];
|
||||
@@ -427,11 +426,11 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
|
||||
$personsAssociated[] = $participation->getPerson();
|
||||
}
|
||||
}
|
||||
return $personsAssociated;
|
||||
return $personsAssociated;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function getPersonsNotAssociated(): array
|
||||
{
|
||||
if (null !== $this->accompanyingPeriod) {
|
||||
@@ -444,7 +443,7 @@ class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPer
|
||||
return $personsNotAssociated;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function setPersons(?Collection $persons): self
|
||||
{
|
||||
|
@@ -36,7 +36,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
$period = $parameters['accompanyingCourse'];
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
|
||||
$menu->addChild($this->translator->trans('Activity'), [
|
||||
$menu->addChild($this->translator->trans('Activity list'), [
|
||||
'route' => 'chill_activity_activity_list',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
|
@@ -23,8 +23,6 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
@@ -35,10 +33,9 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
|
||||
final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
|
||||
final class ActivityACLAwareRepository
|
||||
{
|
||||
private AuthorizationHelper $authorizationHelper;
|
||||
|
||||
@@ -48,63 +45,16 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
CenterResolverDispatcher $centerResolverDispatcher,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
ActivityRepository $repository,
|
||||
EntityManagerInterface $em,
|
||||
Security $security
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->repository = $repository;
|
||||
$this->em = $em;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
* @param string $role
|
||||
* @param int|null $start
|
||||
* @param int|null $limit
|
||||
* @param array $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($person);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$reachableScopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
|
||||
;
|
||||
}
|
||||
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
|
||||
}
|
||||
|
||||
public function queryTimelineIndexer(string $context, array $args = []): array
|
||||
@@ -131,7 +81,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$associationMapping = $metadataActivity->getAssociationMapping('person');
|
||||
|
||||
|
||||
return $metadataActivity->getTableName().' JOIN '
|
||||
.$metadataPerson->getTableName().' ON '
|
||||
.$metadataPerson->getTableName().'.'.
|
||||
@@ -145,7 +95,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
{
|
||||
$where = '';
|
||||
$parameters = [];
|
||||
|
||||
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name'];
|
||||
@@ -155,20 +105,20 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
|
||||
// acls:
|
||||
$role = new Role(ActivityVoter::SEE);
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$role);
|
||||
|
||||
|
||||
if (count($reachableCenters) === 0) {
|
||||
// insert a dummy condition
|
||||
return 'FALSE = TRUE';
|
||||
}
|
||||
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
$where .= sprintf('%s = ? AND ', $activityToPerson);
|
||||
$parameters[] = $person->getId();
|
||||
}
|
||||
|
||||
|
||||
// we add acl (reachable center and scopes)
|
||||
$where .= '('; // first loop for the for centers
|
||||
$centersI = 0; // like centers#i
|
||||
@@ -181,7 +131,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(
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
$reachableScopes
|
||||
);
|
||||
|
||||
@@ -212,7 +162,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte
|
||||
}
|
||||
// close loop for centers
|
||||
$where .= ')';
|
||||
|
||||
|
||||
return [$where, $parameters];
|
||||
}
|
||||
|
||||
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
interface ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
}
|
@@ -23,8 +23,6 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
@@ -41,22 +39,15 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Activity::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person
|
||||
* @param array $scopes
|
||||
* @param string[] $orderBy
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
|
||||
public function findByPersonImplied($person, array $scopes, $orderBy = [ 'date' => 'DESC'], $limit = 100, $offset = 0)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
$qb
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
// TODO add acl
|
||||
//->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
//->setParameter('scopes', $scopes)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('a.person', ':person'),
|
||||
@@ -70,56 +61,7 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriod $period
|
||||
* @param array $scopes
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @param array|string[] $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
if (!$allowNullScope) {
|
||||
$qb
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
} else {
|
||||
$qb
|
||||
->where(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->in('a.scope', ':scopes'),
|
||||
$qb->expr()->isNull('a.scope')
|
||||
)
|
||||
)
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->eq('a.accompanyingPeriod', ':period')
|
||||
)
|
||||
->setParameter('period', $period)
|
||||
;
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ div.activity-list {
|
||||
div.item-row.main {
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-basis: 15%;
|
||||
flex-basis: 27%;
|
||||
}
|
||||
ul.list-content {
|
||||
li.social-issues, li.social-actions {
|
||||
@@ -48,45 +48,42 @@ div.activity-list {
|
||||
}
|
||||
}
|
||||
}
|
||||
div.item-row.comment {
|
||||
margin-left: 15%;
|
||||
blockquote.chill-user-quote {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
div.item-row.details {
|
||||
margin-left: 15%;
|
||||
flex-direction: row;
|
||||
& > div.item-col {
|
||||
justify-content: flex-start;
|
||||
align-self: center;
|
||||
&:nth-child(1) {
|
||||
flex-grow: 1; flex-shrink: 0; flex-basis: 30%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
flex-grow: 0; flex-shrink: 1; flex-basis: 70%;
|
||||
}
|
||||
|
||||
// override flex-bloc to adapt in list
|
||||
// TODO refund this
|
||||
div.accompanyingCourse.flex-bloc.concerned-groups {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
div.item-bloc {
|
||||
box-shadow: unset;
|
||||
padding: 0;
|
||||
flex-basis: 25%;
|
||||
div.item-row {
|
||||
flex-direction: column;
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
width: unset;
|
||||
}
|
||||
&:last-child {
|
||||
border-top: 0;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
ul.list-content {
|
||||
padding: 0;
|
||||
&:only-child {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 100%;
|
||||
& > div.concerned-groups {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 100%;
|
||||
display: flex;
|
||||
flex-direction: column; // TODO pas fini
|
||||
div.group {
|
||||
flex-grow: 1; flex-shrink: 0; flex-basis: 30%;
|
||||
h4 {}
|
||||
ul.list-content {
|
||||
li {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.concerned-groups {
|
||||
font-size: 85%;
|
||||
h4 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
@@ -130,13 +127,3 @@ div.flex-bloc.concerned-groups {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// CHILL ENTITY RENDER BOX
|
||||
.chill-entity {
|
||||
|
||||
/// ACTIVITY-REASON
|
||||
&.entity-activity-reason {
|
||||
margin-right: 0.3em;
|
||||
font-size: 120%;
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<teleport to="#add-persons">
|
||||
|
||||
<div class="flex-bloc concerned-groups" :class="getContext">
|
||||
<persons-bloc
|
||||
<persons-bloc
|
||||
v-for="bloc in contextPersonsBlocs"
|
||||
v-bind:key="bloc.key"
|
||||
v-bind:bloc="bloc"
|
||||
@@ -10,15 +10,7 @@
|
||||
</persons-bloc>
|
||||
</div>
|
||||
|
||||
<div v-if="getContext === 'accompanyingCourse' && filterSuggestedPersons.length > 0">
|
||||
<ul>
|
||||
<li v-for="p in filterSuggestedPersons" @click="addNewPerson(p)">
|
||||
{{ p.text }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<add-persons
|
||||
<add-persons
|
||||
buttonTitle="activity.add_persons"
|
||||
modalTitle="activity.add_persons"
|
||||
v-bind:key="addPersons.key"
|
||||
@@ -26,12 +18,12 @@
|
||||
@addNewPersons="addNewPersons"
|
||||
ref="addPersons">
|
||||
</add-persons>
|
||||
|
||||
</teleport>
|
||||
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
import { mapState } from 'vuex';
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
|
||||
import PersonsBloc from './ConcernedGroups/PersonsBloc.vue';
|
||||
|
||||
@@ -44,29 +36,29 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
personsBlocs: [
|
||||
{ key: 'persons',
|
||||
title: 'activity.bloc_persons',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'persons',
|
||||
title: 'activity.bloc_persons',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'personsAssociated',
|
||||
title: 'activity.bloc_persons_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'personsAssociated',
|
||||
title: 'activity.bloc_persons_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'personsNotAssociated',
|
||||
title: 'activity.bloc_persons_not_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'personsNotAssociated',
|
||||
title: 'activity.bloc_persons_not_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'thirdparty',
|
||||
title: 'activity.bloc_thirdparty',
|
||||
persons: [],
|
||||
{ key: 'thirdparty',
|
||||
title: 'activity.bloc_thirdparty',
|
||||
persons: [],
|
||||
included: true
|
||||
},
|
||||
{ key: 'users',
|
||||
title: 'activity.bloc_users',
|
||||
persons: [],
|
||||
{ key: 'users',
|
||||
title: 'activity.bloc_users',
|
||||
persons: [],
|
||||
included: true
|
||||
},
|
||||
],
|
||||
@@ -87,9 +79,6 @@ export default {
|
||||
users: state => state.activity.users,
|
||||
accompanyingCourse: state => state.activity.accompanyingPeriod
|
||||
}),
|
||||
...mapGetters([
|
||||
'filterSuggestedPersons'
|
||||
]),
|
||||
getContext() {
|
||||
return (this.accompanyingCourse) ? "accompanyingCourse" : "person";
|
||||
},
|
||||
@@ -102,10 +91,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
setPersonsInBloc() {
|
||||
let groups;
|
||||
let groups;
|
||||
if (this.accompanyingCourse) {
|
||||
groups = this.splitPersonsInGroups();
|
||||
}
|
||||
}
|
||||
this.personsBlocs.forEach(bloc => {
|
||||
if (this.accompanyingCourse) {
|
||||
switch (bloc.key) {
|
||||
@@ -120,7 +109,7 @@ export default {
|
||||
}
|
||||
} else {
|
||||
switch (bloc.key) {
|
||||
case 'persons':
|
||||
case 'persons':
|
||||
bloc.persons = this.persons;
|
||||
bloc.included = true;
|
||||
break;
|
||||
@@ -139,7 +128,7 @@ export default {
|
||||
splitPersonsInGroups() {
|
||||
let personsAssociated = [];
|
||||
let personsNotAssociated = this.persons;
|
||||
let participations = this.getCourseParticipations();
|
||||
let participations = this.getCourseParticipations();
|
||||
this.persons.forEach(person => {
|
||||
participations.forEach(participation => {
|
||||
if (person.id === participation.id) {
|
||||
@@ -149,9 +138,9 @@ export default {
|
||||
}
|
||||
});
|
||||
});
|
||||
return {
|
||||
'personsAssociated': personsAssociated,
|
||||
'personsNotAssociated': personsNotAssociated
|
||||
return {
|
||||
'personsAssociated': personsAssociated,
|
||||
'personsNotAssociated': personsNotAssociated
|
||||
};
|
||||
},
|
||||
getCourseParticipations() {
|
||||
@@ -172,11 +161,7 @@ export default {
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
this.setPersonsInBloc();
|
||||
},
|
||||
addNewPerson(person) {
|
||||
this.$store.dispatch('addPersonsInvolved', { result: person, type: 'person' });
|
||||
this.setPersonsInBloc();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -5,175 +5,165 @@ 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({
|
||||
strict: debug,
|
||||
state: {
|
||||
activity: window.activity,
|
||||
socialIssuesOther: [],
|
||||
socialActionsList: [],
|
||||
},
|
||||
getters: {
|
||||
filterSuggestedPersons(state) {
|
||||
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
|
||||
return [];
|
||||
strict: debug,
|
||||
state: {
|
||||
activity: window.activity,
|
||||
socialIssuesOther: [],
|
||||
socialActionsList: [],
|
||||
},
|
||||
mutations: {
|
||||
|
||||
// SocialIssueAcc
|
||||
addIssueInList(state, issue) {
|
||||
//console.log('add issue list', issue.id);
|
||||
state.activity.accompanyingPeriod.socialIssues.push(issue);
|
||||
},
|
||||
addIssueSelected(state, issue) {
|
||||
//console.log('add issue selected', issue.id);
|
||||
state.activity.socialIssues.push(issue);
|
||||
},
|
||||
updateIssuesSelected(state, issues) {
|
||||
//console.log('update issues selected', issues);
|
||||
state.activity.socialIssues = issues;
|
||||
},
|
||||
updateIssuesOther(state, payload) {
|
||||
//console.log('update issues other');
|
||||
state.socialIssuesOther = payload;
|
||||
},
|
||||
removeIssueInOther(state, issue) {
|
||||
//console.log('remove issue other', issue.id);
|
||||
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
|
||||
},
|
||||
resetActionsList(state) {
|
||||
//console.log('reset list actions');
|
||||
state.socialActionsList = [];
|
||||
},
|
||||
addActionInList(state, action) {
|
||||
//console.log('add action list', action.id);
|
||||
state.socialActionsList.push(action);
|
||||
},
|
||||
updateActionsSelected(state, actions) {
|
||||
//console.log('update actions selected', actions);
|
||||
state.activity.socialActions = actions;
|
||||
},
|
||||
filterList(state, list) {
|
||||
const filterList = (list) => {
|
||||
// remove duplicates entries
|
||||
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
|
||||
// alpha sort
|
||||
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
|
||||
return list;
|
||||
};
|
||||
if (list === 'issues') {
|
||||
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
|
||||
}
|
||||
if (list === 'actions') {
|
||||
state.socialActionsList = filterList(state.socialActionsList);
|
||||
}
|
||||
},
|
||||
|
||||
// ConcernedGroups
|
||||
addPersonsInvolved(state, payload) {
|
||||
//console.log('### mutation addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
state.activity.persons.push(payload.result);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties.push(payload.result);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users.push(payload.result);
|
||||
break;
|
||||
};
|
||||
},
|
||||
removePersonInvolved(state, payload) {
|
||||
//console.log('### mutation removePersonInvolved', payload.type);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
state.activity.persons = state.activity.persons.filter(person => person !== payload);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users = state.activity.users.filter(user => user !== payload);
|
||||
break;
|
||||
};
|
||||
}
|
||||
let existingPersonIds = state.activity.persons.map(p => p.id);
|
||||
return state.activity.accompanyingPeriod.participations.filter(p => p.endDate === null)
|
||||
.map(p => p.person)
|
||||
.filter(p => !existingPersonIds.includes(p.id))
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
// SocialIssueAcc
|
||||
addIssueInList(state, issue) {
|
||||
//console.log('add issue list', issue.id);
|
||||
state.activity.accompanyingPeriod.socialIssues.push(issue);
|
||||
},
|
||||
addIssueSelected(state, issue) {
|
||||
//console.log('add issue selected', issue.id);
|
||||
state.activity.socialIssues.push(issue);
|
||||
},
|
||||
updateIssuesSelected(state, issues) {
|
||||
//console.log('update issues selected', issues);
|
||||
state.activity.socialIssues = issues;
|
||||
},
|
||||
updateIssuesOther(state, payload) {
|
||||
//console.log('update issues other');
|
||||
state.socialIssuesOther = payload;
|
||||
},
|
||||
removeIssueInOther(state, issue) {
|
||||
//console.log('remove issue other', issue.id);
|
||||
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
|
||||
},
|
||||
resetActionsList(state) {
|
||||
//console.log('reset list actions');
|
||||
state.socialActionsList = [];
|
||||
},
|
||||
addActionInList(state, action) {
|
||||
//console.log('add action list', action.id);
|
||||
state.socialActionsList.push(action);
|
||||
},
|
||||
updateActionsSelected(state, actions) {
|
||||
//console.log('update actions selected', actions);
|
||||
state.activity.socialActions = actions;
|
||||
},
|
||||
filterList(state, list) {
|
||||
const filterList = (list) => {
|
||||
// remove duplicates entries
|
||||
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
|
||||
// alpha sort
|
||||
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
|
||||
return list;
|
||||
};
|
||||
if (list === 'issues') {
|
||||
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
|
||||
},
|
||||
actions: {
|
||||
addIssueSelected({ commit }, issue) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
|
||||
commit('addIssueSelected', issue);
|
||||
},
|
||||
updateIssuesSelected({ commit }, payload) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
|
||||
});
|
||||
commit('updateIssuesSelected', payload);
|
||||
},
|
||||
updateActionsSelected({ commit }, payload) {
|
||||
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
|
||||
aSocialActions.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
|
||||
});
|
||||
commit('updateActionsSelected', payload);
|
||||
},
|
||||
addPersonsInvolved({ commit }, payload) {
|
||||
//console.log('### action addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
|
||||
break;
|
||||
};
|
||||
commit('addPersonsInvolved', payload);
|
||||
},
|
||||
removePersonInvolved({ commit }, payload) {
|
||||
//console.log('### action removePersonInvolved', payload);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
|
||||
break;
|
||||
};
|
||||
commit('removePersonInvolved', payload);
|
||||
}
|
||||
if (list === 'actions') {
|
||||
state.socialActionsList = filterList(state.socialActionsList);
|
||||
}
|
||||
},
|
||||
|
||||
// ConcernedGroups
|
||||
addPersonsInvolved(state, payload) {
|
||||
//console.log('### mutation addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
state.activity.persons.push(payload.result);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties.push(payload.result);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users.push(payload.result);
|
||||
break;
|
||||
};
|
||||
},
|
||||
removePersonInvolved(state, payload) {
|
||||
//console.log('### mutation removePersonInvolved', payload.type);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
state.activity.persons = state.activity.persons.filter(person => person !== payload);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users = state.activity.users.filter(user => user !== payload);
|
||||
break;
|
||||
};
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
addIssueSelected({ commit }, issue) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
|
||||
commit('addIssueSelected', issue);
|
||||
},
|
||||
updateIssuesSelected({ commit }, payload) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
|
||||
});
|
||||
commit('updateIssuesSelected', payload);
|
||||
},
|
||||
updateActionsSelected({ commit }, payload) {
|
||||
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
|
||||
aSocialActions.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
|
||||
});
|
||||
commit('updateActionsSelected', payload);
|
||||
},
|
||||
addPersonsInvolved({ commit }, payload) {
|
||||
//console.log('### action addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
|
||||
break;
|
||||
};
|
||||
commit('addPersonsInvolved', payload);
|
||||
},
|
||||
removePersonInvolved({ commit }, payload) {
|
||||
//console.log('### action removePersonInvolved', payload);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
|
||||
break;
|
||||
};
|
||||
commit('removePersonInvolved', payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
BIN
src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/app/Resources/.DS_Store
vendored
Normal file
BIN
src/Bundle/ChillActivityBundle/Resources/test/Fixtures/App/app/Resources/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -59,7 +59,7 @@
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
<span class="badge bg-primary">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
@@ -86,7 +86,7 @@
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
<span class="badge bg-primary">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
|
@@ -54,7 +54,7 @@
|
||||
{{ form_row(edit_form.date) }}
|
||||
{% endif %}
|
||||
|
||||
{# TODO .. location #}
|
||||
.. location
|
||||
|
||||
{%- if edit_form.durationTime is defined -%}
|
||||
{{ form_row(edit_form.durationTime) }}
|
||||
@@ -65,7 +65,7 @@
|
||||
{% endif %}
|
||||
|
||||
{%- if edit_form.comment is defined -%}
|
||||
{# TODO .. public and private #}
|
||||
.. public and private
|
||||
{{ form_row(edit_form.comment) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
{{ form_row(edit_form.attendee) }}
|
||||
{% endif %}
|
||||
|
||||
{# TODO .. status #}
|
||||
.. status
|
||||
|
||||
{% set person_id = null %}
|
||||
{% if entity.person %}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
{% if activity.durationTime and t.durationTimeVisible %}
|
||||
{% if t.durationTimeVisible > 0 %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ activity.durationTime|date('H:i') }}
|
||||
@@ -34,150 +34,127 @@
|
||||
</div>
|
||||
|
||||
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
title="{{ 'Period number %number%'|trans({'%number%': activity.accompanyingPeriod.id}) }}"
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}"><i class="fa fa-random"></i>
|
||||
<div class="accompanyingPeriodLink" style="margin-top: 1rem">
|
||||
<a href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}">
|
||||
<i class="fa fa-random"></i>
|
||||
{{ activity.accompanyingPeriod.id }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ activity.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<div class="float-button top">
|
||||
<div class="box">
|
||||
<li>
|
||||
<b>{{ activity.type.name | localize_translatable_string }}</b>
|
||||
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
{% if activity.attendee is not null and t.attendeeVisible %}
|
||||
{% if activity.attendee %}
|
||||
{{ '→ ' ~ 'present'|trans|capitalize }}
|
||||
{% else %}
|
||||
{{ '→ ' ~ 'not present'|trans|capitalize }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>{{ 'location'|trans ~ ': ' }}</b>
|
||||
Domicile de l'usager
|
||||
{#
|
||||
{% if activity.location %}{{ activity.location }}{% endif %}
|
||||
#}
|
||||
</li>
|
||||
|
||||
{%- if t.reasonsVisible -%}
|
||||
<li>
|
||||
{%- if activity.reasons is not empty -%}
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialIssuesVisible %}
|
||||
<li class="social-issues">
|
||||
{%- if activity.socialIssues is not empty -%}
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialActionsVisible -%}
|
||||
<li class="social-actions">
|
||||
{%- if activity.socialActions is not empty -%}
|
||||
{% for r in activity.socialActions %}
|
||||
<span class="badge bg-primary">{{ r.title|localize_translatable_string }}</span>
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-show "></a>
|
||||
</li>
|
||||
{% if no_action is not defined or no_action == false %}
|
||||
{# TODO
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-update "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
|
||||
class="btn btn-sm btn-delete "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
#}
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
|
||||
class="btn btn-sm btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="list-content">
|
||||
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
|
||||
<b>{{ activity.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<b>{{ activity.type.name | localize_translatable_string }}</b>
|
||||
|
||||
{% if activity.attendee is not null and t.attendeeVisible %}
|
||||
{% if activity.attendee %}
|
||||
{{ '→ ' ~ 'present'|trans|capitalize }}
|
||||
{% else %}
|
||||
{{ '→ ' ~ 'not present'|trans|capitalize }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>{{ 'location'|trans ~ ': ' }}</b>
|
||||
Domicile de l'usager
|
||||
|
||||
{# TODO {% if activity.location %}{{ activity.location }}{% endif %}
|
||||
#}
|
||||
|
||||
</li>
|
||||
|
||||
{%- if t.reasonsVisible -%}
|
||||
<li>
|
||||
{%- if activity.reasons is not empty -%}
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialIssuesVisible %}
|
||||
<li class="social-issues">
|
||||
{%- if activity.socialIssues is not empty -%}
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialActionsVisible -%}
|
||||
<li class="social-actions">
|
||||
{%- if activity.socialActions is not empty -%}
|
||||
{% for r in activity.socialActions %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if activity.comment.comment is not empty
|
||||
or activity.persons|length > 0
|
||||
or activity.thirdParties|length > 0
|
||||
or activity.users|length > 0
|
||||
%}
|
||||
<div class="item-row comment separator">
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': activity } %}
|
||||
</div>
|
||||
|
||||
{% if activity.comment.comment is not empty %}
|
||||
{{ activity.comment|chill_entity_render_box({
|
||||
'disable_markdown': false,
|
||||
'limit_lines': 3,
|
||||
'metadata': false,
|
||||
}) }}
|
||||
<div class="item-col">
|
||||
{{ activity.comment|chill_entity_render_box({
|
||||
'disable_markdown': false,
|
||||
'limit_lines': 3,
|
||||
'metadata': false,
|
||||
}) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="item-row details">
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
|
||||
'context': context,
|
||||
'with_display': 'bloc',
|
||||
'entity': activity,
|
||||
'badge_person': true
|
||||
} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new activity' | trans }}
|
||||
|
@@ -36,7 +36,7 @@
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
|
||||
class="btn btn-create disabled" tabindex="-1" role="button" aria-disabled="true">{{ 'Add a new activity' | trans }}
|
||||
|
@@ -55,7 +55,7 @@
|
||||
{{ form_row(form.date) }}
|
||||
{% endif %}
|
||||
|
||||
{# TODO .. location #}
|
||||
.. location
|
||||
|
||||
{%- if form.durationTime is defined -%}
|
||||
{{ form_row(form.durationTime) }}
|
||||
@@ -66,7 +66,7 @@
|
||||
{% endif %}
|
||||
|
||||
{%- if form.comment is defined -%}
|
||||
{# TODO .. public and private #}
|
||||
.. public and private
|
||||
{{ form_row(form.comment) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -78,13 +78,13 @@
|
||||
{{ form_row(form.attendee) }}
|
||||
{% endif %}
|
||||
|
||||
{# TODO .. status #}
|
||||
.. status
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a
|
||||
<a
|
||||
class="btn btn-cancel"
|
||||
{%- if context == 'person' -%}
|
||||
{%- if context == 'person' -%}
|
||||
href="{{ chill_return_path_or('chill_activity_activity_list', { 'person_id': person.id } )}}"
|
||||
{%- else -%}
|
||||
href="{{ chill_return_path_or('chill_activity_activity_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
|
@@ -18,12 +18,7 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<a href="{{ path('chill_activity_activity_new', {
|
||||
'person_id': person_id,
|
||||
'activityType_id': activityType.id,
|
||||
'accompanying_period_id': accompanying_course_id,
|
||||
'activityData': activityData
|
||||
}) }}">
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'activityType_id': activityType.id, 'accompanying_period_id': accompanying_course_id }) }}">
|
||||
|
||||
<div class="bloc btn btn-primary btn-lg btn-block">
|
||||
{{ activityType.name|localize_translatable_string }}
|
||||
|
@@ -64,26 +64,16 @@
|
||||
|
||||
{% 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>
|
||||
<dd>{{ entity.durationTime|date('H:i') }}</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>
|
||||
<dd>{{ entity.travelTime|date('H:i') }}</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if t.commentVisible %}
|
||||
<dt class="inline">{{ 'activity.comment'|trans }}</dt>
|
||||
<dt class="inline">{{ 'Comment'|trans }}</dt>
|
||||
{%- if entity.comment.empty -%}
|
||||
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd>
|
||||
{%- else -%}
|
||||
@@ -130,17 +120,17 @@
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
{# 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">
|
||||
{{ 'Delete'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title 'Show the activity'|trans %}
|
||||
{% block title 'Activity'|trans %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
||||
{% block content -%}
|
||||
<div class="activity-show">
|
||||
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title 'Show the activity'|trans %}
|
||||
{% block title 'Activity'|trans %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
||||
{% block personcontent -%}
|
||||
<div class="activity-show">
|
||||
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock personcontent %}
|
||||
|
@@ -19,11 +19,6 @@
|
||||
|
||||
namespace Chill\ActivityBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
@@ -33,10 +28,11 @@ use Chill\MainBundle\Entity\User;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Voter for Activity class
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||
{
|
||||
@@ -45,37 +41,30 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS';
|
||||
const UPDATE = 'CHILL_ACTIVITY_UPDATE';
|
||||
const DELETE = 'CHILL_ACTIVITY_DELETE';
|
||||
const FULL = 'CHILL_ACTIVITY_FULL';
|
||||
|
||||
private const ALL = [
|
||||
self::CREATE,
|
||||
self::SEE,
|
||||
self::UPDATE,
|
||||
self::DELETE,
|
||||
self::SEE_DETAILS,
|
||||
self::FULL
|
||||
];
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $helper;
|
||||
|
||||
protected VoterHelperInterface $voterHelper;
|
||||
|
||||
protected Security $security;
|
||||
|
||||
public function __construct(
|
||||
Security $security,
|
||||
VoterHelperFactoryInterface $voterHelperFactory
|
||||
) {
|
||||
$this->security = $security;
|
||||
$this->voterHelper = $voterHelperFactory->generate(self::class)
|
||||
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
||||
->addCheckFor(AccompanyingPeriod::class, [self::SEE, self::CREATE])
|
||||
->addCheckFor(Activity::class, self::ALL)
|
||||
->build();
|
||||
public function __construct(AuthorizationHelper $helper)
|
||||
{
|
||||
$this->helper = $helper;
|
||||
}
|
||||
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
return $this->voterHelper->supports($attribute, $subject);
|
||||
if ($subject instanceof Activity) {
|
||||
return \in_array($attribute, $this->getAttributes());
|
||||
} elseif ($subject instanceof Person) {
|
||||
return $attribute === self::SEE
|
||||
||
|
||||
$attribute === self::CREATE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||
@@ -83,34 +72,32 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
if (!$token->getUser() instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($subject instanceof Activity) {
|
||||
if ($subject->getPerson() instanceof Person) {
|
||||
// the context is person: we must have the right to see the person
|
||||
if (!$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException("could not determine context of activity");
|
||||
}
|
||||
|
||||
if ($subject instanceof Person) {
|
||||
$centers = $this->helper->getReachableCenters($token->getUser(), new Role($attribute));
|
||||
|
||||
return \in_array($subject->getCenter(), $centers);
|
||||
}
|
||||
|
||||
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
|
||||
|
||||
/* @var $subject Activity */
|
||||
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
|
||||
}
|
||||
|
||||
private function getAttributes()
|
||||
{
|
||||
return [ self::CREATE, self::SEE, self::UPDATE, self::DELETE,
|
||||
self::SEE_DETAILS ];
|
||||
}
|
||||
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
return self::ALL;
|
||||
return $this->getAttributes();
|
||||
}
|
||||
|
||||
public function getRolesWithoutScope()
|
||||
{
|
||||
return [];
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,37 +35,35 @@ class ActivityReasonRender extends AbstractChillEntityRender
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function renderBox($entity, array $options): string
|
||||
{
|
||||
return
|
||||
$this->getDefaultOpeningBox('activity-reason').
|
||||
'<span class="badge bg-chill-pink">'.
|
||||
'<i class="fa fa-question-circle"></i> '.
|
||||
'<span class="category">'.
|
||||
'<span class="activity-reason__category">'.
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getCategory()->getName()
|
||||
).
|
||||
'</span>'.
|
||||
'<span class="separator"> > </span>'.
|
||||
'<span class="reason">'.
|
||||
'<span class="activity-reason__separator"> > </span>'.
|
||||
'<span class="activity-reason__reason">'.
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getName()
|
||||
).
|
||||
'</span>'.
|
||||
'</span>'.
|
||||
$this->getDefaultClosingBox()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param ActivityReason $entity
|
||||
* @param array $options
|
||||
* @return string
|
||||
@@ -73,12 +71,12 @@ class ActivityReasonRender extends AbstractChillEntityRender
|
||||
public function renderString($entity, array $options): string
|
||||
{
|
||||
$category = '';
|
||||
|
||||
|
||||
if (null !== $entity->getCategory()) {
|
||||
$category = $this->translatableStringHelper->localize(
|
||||
$entity->getCategory()->getName()). ' > ';
|
||||
}
|
||||
|
||||
|
||||
return $category .
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getName()
|
||||
|
@@ -1,4 +1,20 @@
|
||||
services:
|
||||
chill.activity.security.authorization.activity_voter:
|
||||
class: Chill\ActivityBundle\Security\Authorization\ActivityVoter
|
||||
arguments:
|
||||
- "@chill.main.security.authorization.helper"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
- { name: chill.role }
|
||||
|
||||
chill.activity.security.authorization.activity_stats_voter:
|
||||
class: Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter
|
||||
arguments:
|
||||
- "@chill.main.security.authorization.helper"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
- { name: chill.role }
|
||||
|
||||
|
||||
chill.activity.timeline:
|
||||
class: Chill\ActivityBundle\Timeline\TimelineActivityProvider
|
||||
@@ -22,8 +38,3 @@ services:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Notification'
|
||||
|
||||
Chill\ActivityBundle\Security\Authorization\:
|
||||
resource: '../Security/Authorization/'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@@ -1,14 +0,0 @@
|
||||
services:
|
||||
accompanying_period_social_issue_consistency_for_activity:
|
||||
class: 'Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodSocialIssueConsistencyEntityListener'
|
||||
tags:
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'prePersist'
|
||||
entity: 'Chill\ActivityBundle\Entity\Activity'
|
||||
lazy: true
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'preUpdate'
|
||||
entity: 'Chill\ActivityBundle\Entity\Activity'
|
||||
lazy: true
|
@@ -1,4 +1,8 @@
|
||||
services:
|
||||
Chill\ActivityBundle\Controller\ActivityController:
|
||||
autowire: true
|
||||
arguments:
|
||||
$eventDispatcher: '@Symfony\Component\EventDispatcher\EventDispatcherInterface'
|
||||
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
|
||||
$logger: '@chill.main.logger'
|
||||
$serializer: '@Symfony\Component\Serializer\SerializerInterface'
|
||||
tags: ['controller.service_arguments']
|
||||
|
@@ -24,7 +24,9 @@ services:
|
||||
- '@Doctrine\Persistence\ManagerRegistry'
|
||||
|
||||
Chill\ActivityBundle\Repository\ActivityACLAwareRepository:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface: '@Chill\ActivityBundle\Repository\ActivityACLAwareRepository'
|
||||
arguments:
|
||||
$tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'
|
||||
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
|
||||
$repository: '@Chill\ActivityBundle\Repository\ActivityRepository'
|
||||
$em: '@Doctrine\ORM\EntityManagerInterface'
|
||||
|
||||
|
@@ -81,9 +81,9 @@ activity:
|
||||
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
|
||||
|
||||
#controller
|
||||
'Success : activity created!': L'activité a été créée.
|
||||
'Success : activity created!': Bravo ! L'activité a été créée.
|
||||
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'activité n'a pas été créée.
|
||||
'Success : activity updated!': L'activité a été mise à jour.
|
||||
'Success : activity updated!': Bravo ! L'activité a été mise à jour.
|
||||
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'activité n'a pas été mise à jour.
|
||||
|
||||
# ROLES
|
||||
|
@@ -3,9 +3,6 @@
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
|
||||
/**
|
||||
@@ -13,12 +10,5 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*/
|
||||
class AsideActivityCategoryController extends CRUDController
|
||||
{
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var QueryBuilder $query */
|
||||
$query->addOrderBy('e.ordering', 'ASC');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,71 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
final class AsideActivityController extends CRUDController
|
||||
|
||||
/**
|
||||
* Class AsideActivityBundle
|
||||
*/
|
||||
class AsideActivityController extends CRUDController
|
||||
{
|
||||
|
||||
private $categoryRepository;
|
||||
|
||||
public function __construct(AsideActivityCategoryRepository $categoryRepository)
|
||||
{
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
}
|
||||
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request);
|
||||
|
||||
if ('index' === $action) {
|
||||
$qb->where($qb->expr()->eq('e.agent', ':user'));
|
||||
$qb->orWhere($qb->expr()->eq('e.createdBy', ':user'));
|
||||
$qb->setParameter('user', $this->getUser());
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
protected function orderQuery(
|
||||
string $action,
|
||||
$query,
|
||||
Request $request,
|
||||
PaginatorInterface $paginator
|
||||
) {
|
||||
if ('index' === $action) {
|
||||
return $query->orderBy('e.date', 'DESC');
|
||||
}
|
||||
|
||||
return parent::orderQuery($action, $query, $request, $paginator);
|
||||
}
|
||||
|
||||
public function createEntity(string $action, Request $request): object
|
||||
{
|
||||
$asideActivity = new AsideActivity();
|
||||
|
||||
$duration = $request->query->get('duration', '300');
|
||||
$duration = \DateTime::createFromFormat('U', $duration);
|
||||
$asideActivity->setDuration($duration);
|
||||
|
||||
$categoryId = $request->query->get('type', 7);
|
||||
if($categoryId === null){
|
||||
return $this->createNotFoundException('You must give a valid category id');
|
||||
}
|
||||
$category = $this->categoryRepository->find($categoryId);
|
||||
$asideActivity->setType($category);
|
||||
|
||||
$note = $request->query->get('note', null);
|
||||
$asideActivity->setNote($note);
|
||||
|
||||
return $asideActivity;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadAsideActivity extends Fixture implements DependentFixtureInterface
|
||||
{
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(UserRepository $userRepository)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
public function getDependencies(): array
|
||||
{
|
||||
return [
|
||||
LoadUsers::class,
|
||||
LoadAsideActivityCategory::class
|
||||
];
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$user = $this->userRepository->findOneBy(['username' => 'center a_social']);
|
||||
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
$activity = new AsideActivity();
|
||||
$activity
|
||||
->setAgent($user)
|
||||
->setCreatedAt(new \DateTimeImmutable('now'))
|
||||
->setCreatedBy($user)
|
||||
->setUpdatedAt(new \DateTimeImmutable('now'))
|
||||
->setUpdatedBy($user)
|
||||
->setType(
|
||||
$this->getReference('aside_activity_category_0')
|
||||
)
|
||||
->setDate((new \DateTimeImmutable('today'))
|
||||
->sub(new \DateInterval('P'.\random_int(1, 100).'D')))
|
||||
;
|
||||
|
||||
$manager->persist($activity);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadAsideActivityCategory extends \Doctrine\Bundle\FixturesBundle\Fixture
|
||||
{
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach ([
|
||||
'Appel téléphonique',
|
||||
'Formation'
|
||||
] as $key => $label) {
|
||||
$category = new AsideActivityCategory();
|
||||
$category->setTitle(['fr' => $label]);
|
||||
$manager->persist($category);
|
||||
$this->setReference('aside_activity_category_'.$key, $category);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -24,16 +24,9 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$container->setParameter('chill_aside_activity.form.time_duration', $config['form']['time_duration']);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
|
||||
$loader->load('services.yaml');
|
||||
// $loader->load('services.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
$loader->load('services/menu.yaml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
@@ -87,7 +80,7 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
|
||||
'controller' => \Chill\AsideActivityBundle\Controller\AsideActivityController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'template' => '@ChillAsideActivity/asideActivity/index.html.twig',
|
||||
'template' => '@ChillAsideActivity/asideActivity/list.html.twig',
|
||||
'role' => 'ROLE_USER'
|
||||
],
|
||||
'new' => [
|
||||
|
@@ -1,138 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('chill_aside_activity');
|
||||
|
||||
$treeBuilder->getRootNode('chill_aside_activity')
|
||||
->children()
|
||||
->arrayNode('form')
|
||||
->canBeEnabled()
|
||||
->children()
|
||||
->arrayNode('time_duration')
|
||||
->isRequired()
|
||||
->defaultValue(
|
||||
[
|
||||
[ 'label' => '5 minutes', 'seconds' => 300],
|
||||
[ 'label' => '10 minutes', 'seconds' => 600],
|
||||
[ 'label' => '15 minutes', 'seconds' => 900],
|
||||
[ 'label' => '20 minutes', 'seconds' => 1200],
|
||||
[ 'label' => '25 minutes', 'seconds' => 1500],
|
||||
[ 'label' => '30 minutes', 'seconds' => 1800],
|
||||
[ 'label' => '45 minutes', 'seconds' => 2700],
|
||||
[ 'label' => '1 hour', 'seconds' => 3600],
|
||||
[ 'label' => '1 hour 15', 'seconds' => 4500],
|
||||
[ 'label' => '1 hour 30', 'seconds' => 5400],
|
||||
[ 'label' => '1 hour 45', 'seconds' => 6300],
|
||||
[ 'label' => '2 hours', 'seconds' => 7200],
|
||||
[ 'label' => '2 hours 30', 'seconds' => 9000],
|
||||
[ 'label' => '3 hours', 'seconds' => 10800],
|
||||
[ 'label' => '3 hours 30', 'seconds' => 12600],
|
||||
[ 'label' => '4 hours', 'seconds' => 14400],
|
||||
[ 'label' => '4 hours 30', 'seconds' => 16200],
|
||||
[ 'label' => '5 hours', 'seconds' => 18000],
|
||||
[ 'label' => '5 hours 30', 'seconds' => 19800],
|
||||
[ 'label' => '6 hours', 'seconds' => 21600],
|
||||
[ 'label' => '6 hours 30', 'seconds' => 23400],
|
||||
[ 'label' => '7 hours', 'seconds' => 25200],
|
||||
[ 'label' => '7 hours 30', 'seconds' => 27000],
|
||||
[ 'label' => '8 hours', 'seconds' => 28800],
|
||||
[ 'label' => '8 hours 30', 'seconds' => 30600],
|
||||
[ 'label' => '9 hours', 'seconds' => 32400],
|
||||
[ 'label' => '9 hours 30', 'seconds' => 34200],
|
||||
[ 'label' => '10 hours', 'seconds' => 36000],
|
||||
[ 'label' => '1/2 day', 'seconds' => 14040],
|
||||
[ 'label' => '1 day', 'seconds' => 28080],
|
||||
[ 'label' => '1 1/2 days', 'seconds' => 42120],
|
||||
[ 'label' => '2 days', 'seconds' => 56160],
|
||||
[ 'label' => '2 1/2 days', 'seconds' => 70200],
|
||||
[ 'label' => '3 days', 'seconds' => 84240],
|
||||
[ 'label' => '3 1/2 days', 'seconds' => 98280],
|
||||
[ 'label' => '4 days', 'seconds' => 112320],
|
||||
[ 'label' => '4 1/2 days', 'seconds' => 126360],
|
||||
[ 'label' => '5 days', 'seconds' => 140400],
|
||||
[ 'label' => '5 1/2 days', 'seconds' => 154440],
|
||||
[ 'label' => '6 days', 'seconds' => 168480],
|
||||
[ 'label' => '6 1/2 days', 'seconds' => 182520],
|
||||
[ 'label' => '7 days', 'seconds' => 196560],
|
||||
[ 'label' => '7 1/2 days', 'seconds' => 210600],
|
||||
[ 'label' => '8 days', 'seconds' => 224640],
|
||||
[ 'label' => '8 1/2 days', 'seconds' => 238680],
|
||||
[ 'label' => '9 days', 'seconds' => 252720],
|
||||
[ 'label' => '9 1/2 days', 'seconds' => 266760],
|
||||
[ 'label' => '10 days', 'seconds' => 280800],
|
||||
[ 'label' => '10 1/2days', 'seconds' => 294840],
|
||||
[ 'label' => '11 days', 'seconds' => 308880],
|
||||
[ 'label' => '11 1/2 days', 'seconds' => 322920],
|
||||
[ 'label' => '12 days', 'seconds' => 336960],
|
||||
[ 'label' => '12 1/2 days', 'seconds' => 351000],
|
||||
[ 'label' => '13 days', 'seconds' => 365040],
|
||||
[ 'label' => '13 1/2 days', 'seconds' => 379080],
|
||||
[ 'label' => '14 days', 'seconds' => 393120],
|
||||
[ 'label' => '14 1/2 days', 'seconds' => 407160],
|
||||
[ 'label' => '15 days', 'seconds' => 421200],
|
||||
[ 'label' => '15 1/2 days', 'seconds' => 435240],
|
||||
[ 'label' => '16 days', 'seconds' => 449280],
|
||||
[ 'label' => '16 1/2 days', 'seconds' => 463320],
|
||||
[ 'label' => '17 days', 'seconds' => 477360],
|
||||
[ 'label' => '17 1/2 days', 'seconds' => 491400],
|
||||
[ 'label' => '18 days', 'seconds' => 505440],
|
||||
[ 'label' => '18 1/2 days', 'seconds' => 519480],
|
||||
[ 'label' => '19 days', 'seconds' => 533520],
|
||||
[ 'label' => '19 1/2 days', 'seconds' => 547560],
|
||||
[ 'label' => '20 days', 'seconds' => 561600],
|
||||
[ 'label' => '20 1/2 days', 'seconds' => 575640],
|
||||
[ 'label' => '21 days', 'seconds' => 580680],
|
||||
[ 'label' => '21 1/2 days', 'seconds' => 603720],
|
||||
[ 'label' => '22 days', 'seconds' => 617760],
|
||||
[ 'label' => '22 1/2 days', 'seconds' => 631800],
|
||||
[ 'label' => '23 days', 'seconds' => 645840],
|
||||
[ 'label' => '23 1/2 days', 'seconds' => 659880],
|
||||
[ 'label' => '24 days', 'seconds' => 673920],
|
||||
[ 'label' => '24 1/2 days', 'seconds' => 687960],
|
||||
[ 'label' => '25 days', 'seconds' => 702000],
|
||||
[ 'label' => '25 1/2 days', 'seconds' => 716040],
|
||||
[ 'label' => '26 days', 'seconds' => 730080],
|
||||
[ 'label' => '26 1/2 days', 'seconds' => 744120],
|
||||
[ 'label' => '27 days', 'seconds' => 758160],
|
||||
[ 'label' => '27 1/2 days', 'seconds' => 772200],
|
||||
[ 'label' => '28 days', 'seconds' => 786240],
|
||||
[ 'label' => '28 1/2 days', 'seconds' => 800280],
|
||||
[ 'label' => '29 days', 'seconds' => 814320],
|
||||
[ 'label' => '29 1/2 days', 'seconds' => 828360],
|
||||
[ 'label' => '30 days', 'seconds' => 842400],
|
||||
]
|
||||
)
|
||||
->info('The intervals of time to show in activity form')
|
||||
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('seconds')
|
||||
->info("The number of seconds of this duration. Must be an integer.")
|
||||
->cannotBeEmpty()
|
||||
->validate()
|
||||
->ifTrue(function($data) {
|
||||
return !is_int($data);
|
||||
})->thenInvalid("The value %s is not a valid integer")
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('label')
|
||||
->cannotBeEmpty()
|
||||
->info("The label to show into fields")
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
@@ -200,4 +200,10 @@ class AsideActivity implements TrackUpdateInterface, TrackCreationInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// public function __toString()
|
||||
// {
|
||||
// // dump($this->type->getTitle());
|
||||
// return $this->type->getTitle();
|
||||
// }
|
||||
}
|
||||
|
@@ -7,8 +7,6 @@ namespace Chill\AsideActivityBundle\Entity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
@@ -29,33 +27,10 @@ class AsideActivityCategory
|
||||
private array $title;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private bool $isActive = true;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
* @ORM\Column(type="float", options={"default": 0.00})
|
||||
*/
|
||||
private float $ordering = 0.00;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AsideActivityCategory::class, inversedBy="children")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -84,85 +59,4 @@ class AsideActivityCategory
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent(): ?self
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Assert\Callback()
|
||||
*/
|
||||
public function preventRecursiveParent(ExecutionContextInterface $context, $payload)
|
||||
{
|
||||
if (!$this->hasParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getParent() === $this) {
|
||||
// replace parent with old parent. This prevent recursive loop
|
||||
// when displaying form
|
||||
$this->parent = $this->oldParent;
|
||||
$context->buildViolation('You must not add twice the same category in the parent tree (previous result returned)')
|
||||
->atPath('parent')
|
||||
->addViolation()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
public function setParent(?self $parent): self
|
||||
{
|
||||
// cache the old result for changing it during validaiton
|
||||
$this->oldParent = $this->parent;
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|self[]
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
public function addChild(self $child): self
|
||||
{
|
||||
if (!$this->children->contains($child)) {
|
||||
$this->children[] = $child;
|
||||
$child->setParent($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeChild(self $child): self
|
||||
{
|
||||
if ($this->children->removeElement($child)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($child->getParent() === $this) {
|
||||
$child->setParent(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrdering(): float
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
public function setOrdering(float $ordering): AsideActivityCategory
|
||||
{
|
||||
$this->ordering = $ordering;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -3,43 +3,21 @@
|
||||
namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class AsideActivityCategoryType extends AbstractType
|
||||
{
|
||||
|
||||
protected $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, CategoryRender $categoryRender)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('title', TranslatableStringFormType::class,
|
||||
[
|
||||
'label' => 'Nom',
|
||||
])
|
||||
->add('parent', EntityType::class, [
|
||||
'class' => AsideActivityCategory::class,
|
||||
'required' => false,
|
||||
'label' => 'Parent',
|
||||
'choice_label' => function (AsideActivityCategory $category){
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($category, $options);
|
||||
}
|
||||
])
|
||||
->add('ordering', NumberType::class)
|
||||
->add('isActive', ChoiceType::class,
|
||||
->add('isActive', ChoiceType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'Yes' => true,
|
||||
|
@@ -4,41 +4,28 @@ namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\ChillTextareaType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class AsideActivityFormType extends AbstractType
|
||||
{
|
||||
protected array $timeChoices;
|
||||
private TokenStorageInterface $storage;
|
||||
private CategoryRender $categoryRender;
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct (
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ParameterBagInterface $parameterBag,
|
||||
TokenStorageInterface $storage,
|
||||
CategoryRender $categoryRender
|
||||
){
|
||||
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
||||
public function __construct (TranslatableStringHelper $translatableStringHelper, array $timeChoices){
|
||||
$this->timeChoices = $timeChoices;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->storage = $storage;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@@ -56,16 +43,12 @@ final class AsideActivityFormType extends AbstractType
|
||||
];
|
||||
|
||||
$builder
|
||||
->add('agent', EntityType::class,
|
||||
->add('agent', EntityType::class,
|
||||
[
|
||||
'label' => 'Agent',
|
||||
'required' => true,
|
||||
'class' => User::class,
|
||||
'data' => $this->storage->getToken()->getUser(),
|
||||
'query_builder' => function(EntityRepository $er){
|
||||
return $er->createQueryBuilder('u')->where('u.enabled = true');
|
||||
},
|
||||
'attr' => array('class' => 'select2 '),
|
||||
//translate
|
||||
'placeholder' => 'Choose the agent for whom this activity is created',
|
||||
'choice_label' => 'username'
|
||||
])
|
||||
@@ -73,6 +56,11 @@ final class AsideActivityFormType extends AbstractType
|
||||
[
|
||||
'label' => 'date',
|
||||
'data' => new \DateTime(),
|
||||
//SETTING RANGE ONLY POSSIBLE WITH WIDGET 'CHOICE' AND NOT 'SINGLE_TEXT'?
|
||||
// 'widget' => 'choice',
|
||||
// 'years' => range(2020, date('Y')),
|
||||
// 'months' => range(1, date('m')),
|
||||
// 'days' => range(1, date('d')),
|
||||
'required' => true
|
||||
])
|
||||
->add('type', EntityType::class,
|
||||
@@ -81,17 +69,9 @@ final class AsideActivityFormType extends AbstractType
|
||||
'required' => true,
|
||||
'class' => AsideActivityCategory::class,
|
||||
'placeholder' => 'Choose the activity category',
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('ac');
|
||||
$qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
|
||||
->addOrderBy('ac.ordering', 'ASC')
|
||||
;
|
||||
|
||||
return $qb;
|
||||
},
|
||||
// 'choice_label' => 'title[""]'
|
||||
'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($asideActivityCategory, $options);
|
||||
return $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
},
|
||||
])
|
||||
->add('duration', ChoiceType::class, $durationTimeOptions)
|
||||
@@ -100,7 +80,7 @@ final class AsideActivityFormType extends AbstractType
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
foreach (['duration'] as $fieldName)
|
||||
foreach (['duration'] as $fieldName)
|
||||
{
|
||||
$builder->get($fieldName)
|
||||
->addModelTransformer($durationTimeTransformer);
|
||||
@@ -123,6 +103,7 @@ final class AsideActivityFormType extends AbstractType
|
||||
$seconds = $data->getTimezone()->getOffset($data);
|
||||
$data->setTimeZone($timezoneUTC);
|
||||
$data->add(new \DateInterval('PT'.$seconds.'S'));
|
||||
dump($data);
|
||||
|
||||
// test if the timestamp is in the choices.
|
||||
// If not, recreate the field with the new timestamp
|
||||
@@ -145,7 +126,7 @@ final class AsideActivityFormType extends AbstractType
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => AsideActivity::class,
|
||||
'data_class' => AsideActivity::class,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -153,4 +134,4 @@ final class AsideActivityFormType extends AbstractType
|
||||
{
|
||||
return 'chill_asideactivitybundle_asideactivity';
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['admin_index', 'admin_section', 'admin_aside_activity'];
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
// all the entries below must have ROLE_ADMIN permissions
|
||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($menuId, ['admin_index', 'admin_section'])) {
|
||||
$menu->addChild('Aside activities', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 900,
|
||||
'explain' => "Configure aside activities categories"
|
||||
]);
|
||||
} else {
|
||||
$menu
|
||||
->addChild('Aside activity categories', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => '50'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Class SectionMenuBuilder
|
||||
*
|
||||
* @package Chill\AsideActivityBundle\Menu
|
||||
*/
|
||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
protected TranslatorInterface $translator;
|
||||
public AuthorizationCheckerInterface $authorizationChecker;
|
||||
|
||||
public function __construct(TranslatorInterface $translator, AuthorizationCheckerInterface $authorizationChecker)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $menuId
|
||||
* @param MenuItem $menu
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild($this->translator->trans('Create an aside activity'), [
|
||||
'route' => 'chill_crud_aside_activity_new'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 11,
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
$menu->addChild($this->translator->trans('Phonecall'), [
|
||||
'route' => 'chill_crud_aside_activity_new',
|
||||
'routeParameters' => [
|
||||
'type' => 1,
|
||||
'duration' => 900,
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 12,
|
||||
'icons' => ['plus']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'section' ];
|
||||
}
|
||||
}
|
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs Libres Cooperative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Chill\TaskBundle\Templating\UI\CountNotificationTask;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class UserMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CountNotificationTask
|
||||
*/
|
||||
public $counter;
|
||||
|
||||
/*
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
public $tokenStorage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
public $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
public $authorizationChecker;
|
||||
|
||||
public function __construct(
|
||||
CountNotificationTask $counter,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
TranslatorInterface $translator,
|
||||
AuthorizationCheckerInterface $authorizationChecker
|
||||
) {
|
||||
$this->counter = $counter;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild("My aside activities", [
|
||||
'route' => 'chill_crud_aside_activity_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 10,
|
||||
'icon' => 'tasks'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'user' ];
|
||||
}
|
||||
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_aside_activity') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}
|
||||
<!-- block personcontent empty -->
|
||||
<h1>{{ 'Aside activity configuration'|trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@@ -1,12 +0,0 @@
|
||||
{% set reversed_parents = parents|reverse %}
|
||||
<span
|
||||
class="chill-entity entity-aside_activity-category">
|
||||
{%- for p in reversed_parents %}
|
||||
<span class="parent-{{ loop.revindex0 }}">
|
||||
{{ p.title|localize_translatable_string }}{{ options['default.separator'] }}
|
||||
</span>
|
||||
{%- endfor -%}
|
||||
<span class="child">
|
||||
{{ asideActivityCategory.title|localize_translatable_string }}
|
||||
</span>
|
||||
</span>
|
@@ -1,30 +1,37 @@
|
||||
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
<p class="message-confirm">{{ ('crud.'~crud_name~'.confirm_message_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</p>
|
||||
<p class="message-confirm">{{ ('crud.'~crud_name~'.confirm_message_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</p>
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_start(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
{% block content_form_actions_back %}
|
||||
<li class="cancel">
|
||||
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">
|
||||
{{ 'Cancel'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_before %}
|
||||
<ul class="record_actions">
|
||||
{% block content_form_actions_back %}
|
||||
<li class="cancel">
|
||||
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">
|
||||
{{ 'Cancel'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_before %}{% endblock %}
|
||||
{% block content_form_actions_view %}
|
||||
{% if is_granted(chill_crud_config('role', crud_name, 'view'), entity) %}
|
||||
<li class="">
|
||||
<a class="btn btn-show" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_view', { 'id': entity.id }) }}">
|
||||
{{ 'crud.edit.back_to_view'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content_form_actions_confirm_delete %}
|
||||
<li>
|
||||
<button type="submit" class="btn btn-delete" value="delete-and-close">{{ ('crud.'~crud_name~'.button_delete')|trans }}</button>
|
||||
</li>
|
||||
{% endblock content_form_actions_confirm_delete %}
|
||||
{% block content_form_actions_after %}{% endblock %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
{% block content_form_actions_confirm_delete %}
|
||||
<li>
|
||||
<button type="submit" class="btn btn-delete" value="delete-and-close">{{ ('crud.'~crud_name~'.button_delete')|trans }}</button>
|
||||
</li>
|
||||
{% endblock content_form_actions_confirm_delete %}
|
||||
{% block content_form_actions_after %}{% endblock %}
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
@@ -3,6 +3,6 @@
|
||||
{# {% block title %}{{ ('crud.' ~ crud_name ~ '.delete.title')|trans({'%crud_name%': crud_name}) }}{% endblock %} #}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillAsideActivity/asideActivity/_delete.html.twig' %}
|
||||
{% embed '@ChillAsideActivity/AsideActivity/_delete.html.twig' %}
|
||||
{% endembed %}
|
||||
{% endblock content %}
|
||||
{% endblock content %}
|
@@ -9,6 +9,5 @@
|
||||
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||
{# we do not have "view" page. We empty the corresponding block #}
|
||||
{% block content_form_actions_view %}{% endblock %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
@@ -1,91 +1,8 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{{ 'Aside activity list'|trans }}
|
||||
{% endblock title %}
|
||||
{% block title %}{{ ('crud.' ~ crud_name ~ '.index.title')|trans({'%crud_name%': crud_name}) }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 asideactivity-list">
|
||||
<h2>{{ 'My aside activities'|trans }}</h2>
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There aren't any aside activities."|trans }}
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table">
|
||||
|
||||
{% for entity in entities %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row wrap-header">
|
||||
|
||||
<div class="item-col">
|
||||
<h3>
|
||||
{{ entity.type|chill_entity_render_box }}
|
||||
</h3>
|
||||
<div>
|
||||
{% if entity.date %}
|
||||
<span>{{ entity.date|format_date('long') }}</span>
|
||||
{% endif %}
|
||||
{% if entity.date %}
|
||||
<span class="duration">
|
||||
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ entity.duration|date('H:i') }}
|
||||
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<div class="box">
|
||||
<ul class="list-content fa-ul">
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
||||
<b>{{ entity.createdBy|chill_entity_render_box }}</b>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
||||
<b>{{ entity.agent|chill_entity_render_box }}</b>
|
||||
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_view', { 'id': entity.id } ) }}" class="btn btn-show btn-mini"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_edit', { 'id': entity.id }) }}" class="btn btn-update btn-mini "></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_delete', { 'id': entity.id } ) }}" class="btn btn-delete btn-mini"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_new') }}" class="btn btn-create">
|
||||
{{ 'Create'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
{% embed '@ChillAsideActivity/AsideActivity/_index.html.twig' %}
|
||||
{% endembed %}
|
||||
{% endblock content %}
|
@@ -0,0 +1,108 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 col-xxl asideactivity-list">
|
||||
<h2>{{ 'My aside activities' |trans }}</h2>
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There isn't any activities."|trans }}
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table my-4 list-records">
|
||||
{# Sort activities according to date in descending order #}
|
||||
{% for entity in entities|sort ((a, b) => b.date <=> a.date) %}
|
||||
{% set t = entity.type %}
|
||||
|
||||
{# only load aside activities of current user. #}
|
||||
{% if entity.agent == app.user %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
<h3>
|
||||
<b>{{ entity.type.title | localize_translatable_string }}</b>
|
||||
</h3>
|
||||
|
||||
{% if entity.date %}
|
||||
<p>{{ entity.date|format_date('long') }}</p>
|
||||
{% endif %}
|
||||
{#
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ entity.duration|date('H:i') }}
|
||||
</p>
|
||||
</div> #}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if entity.createdBy %}
|
||||
<li>
|
||||
<b>{{ 'Created by: '|trans }}{{ entity.createdBy.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# {%
|
||||
if entity.note is not empty
|
||||
or entity.createdBy|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
{% if entity.note is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ entity.note|chill_markdown_to_html }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endif %} #}
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_view', { 'id': entity.id} ) }}" class="btn btn-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_edit', { 'id': entity.id }) }}" class="btn btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_delete', { 'id': entity.id } ) }}" class="btn btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{# TODO set this condition in configuration #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create">
|
||||
{{ 'Add a new activity' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
@@ -3,50 +3,13 @@
|
||||
{% set activeRouteKey = '' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_view_title.html.twig') %}
|
||||
{% include('@ChillMain/CRUD/_view_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillMain/CRUD/_view_content.html.twig' %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_view')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% block crud_content_view_details %}
|
||||
<dl class="chill_view_data">
|
||||
|
||||
<dt class="inline">{{ 'Type'|trans }}</dt>
|
||||
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
||||
<dd>{{ entity.createdBy }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
||||
<dd>{{ entity.agent }}</dd>
|
||||
|
||||
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
|
||||
|
||||
<dt class="inline">{{ 'Date'|trans }}</dt>
|
||||
<dd>{{ entity.date|format_date('long') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Duration'|trans }}</dt>
|
||||
<dd>{{ entity.duration|date('H:i') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Remark'|trans }}</dt>
|
||||
{%- if entity.note is empty -%}
|
||||
<dd>
|
||||
<span class="chill-no-data-statement">{{ 'No comments'|trans }}</span>
|
||||
</dd>
|
||||
{%- else -%}
|
||||
<dd>
|
||||
<section class="chill-entity entity-comment-embeddable">
|
||||
<blockquote class="chill-user-quote">
|
||||
<p>{{ entity.note }}</p>
|
||||
</blockquote>
|
||||
</section>
|
||||
</dd>
|
||||
{%- endif -%}
|
||||
</dl>
|
||||
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
{% embed '@ChillMain/CRUD/_view_content.html.twig' %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_view')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -1,4 +1,4 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
|
@@ -1,46 +1,44 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'Aside Activity Type list'|trans }}</h1>
|
||||
<h1>{{ 'ActivityType list'|trans }}</h1>
|
||||
|
||||
<table class="records_list table table-bordered border-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Ordering'|trans }}</th>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.ordering }}</td>
|
||||
<td>{{ entity|chill_entity_render_box }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.isActive -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_category_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="records_list table table-bordered border-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.title|localize_translatable_string }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.isActive -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_category_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_category_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new aside activity type'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_type_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new activity type'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||
|
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Templating\Entity;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class CategoryRender implements ChillEntityRenderInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private EngineInterface $engine;
|
||||
|
||||
public const SEPERATOR_KEY = 'default.separator';
|
||||
public const DEFAULT_ARGS = [
|
||||
self::SEPERATOR_KEY => ' > '
|
||||
];
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, EngineInterface $engine)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderString($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
|
||||
while ($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $asideActivityCategory->getParent();
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
}
|
||||
|
||||
$titles = array_reverse($titles);
|
||||
|
||||
return implode($options[self::SEPERATOR_KEY], $titles);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function supports($asideActivityCategory, array $options): bool
|
||||
{
|
||||
return $asideActivityCategory instanceof AsideActivityCategory;
|
||||
}
|
||||
|
||||
public function buildParents(AsideActivityCategory $asideActivityCategory)
|
||||
{
|
||||
$parents = [];
|
||||
|
||||
while($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $parents[] = $asideActivityCategory->getParent();
|
||||
}
|
||||
|
||||
return $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderBox($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
$parents = $this->buildParents($asideActivityCategory);
|
||||
|
||||
return $this->engine->render('@ChillAsideActivity/Entity/asideActivityCategory.html.twig',
|
||||
[
|
||||
'asideActivityCategory' => $asideActivityCategory,
|
||||
'parents' => $parents,
|
||||
'options' => $options
|
||||
]);
|
||||
}
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Tests\Controller;
|
||||
|
||||
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
|
||||
class AccompanyingCourseControllerTest extends WebTestCase
|
||||
{
|
||||
use PrepareClientTrait;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
self::bootKernel();
|
||||
$this->client = $this->getClientAuthenticated();
|
||||
}
|
||||
|
||||
public function testIndexWithoutUsers()
|
||||
{
|
||||
$this->client->request('GET', '/fr/asideactivity');
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testNewWithoutUsers()
|
||||
{
|
||||
$this->client->request('GET', '/fr/asideactivity/new');
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider generateAsideActivityId
|
||||
*/
|
||||
|
||||
public function testEditWithoutUsers(int $asideActivityId)
|
||||
{
|
||||
$this->client->request('GET', "/fr/asideactivity/{$asideActivityId}/edit");
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function generateAsideActivityId()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$qb = self::$container->get(EntityManagerInterface::class)
|
||||
->createQueryBuilder();
|
||||
|
||||
$asideActivityIds = $qb
|
||||
->select('DISTINCT asideactivity.id')
|
||||
->from(AsideActivity::class, 'asideactivity')
|
||||
->innerJoin('asideactivity.agent', 'agent')
|
||||
->where($qb->expr()->eq('agent.username', ':center_name'))
|
||||
->setParameter('center_name', 'center a_social')
|
||||
->setMaxResults(100)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
|
||||
\shuffle($asideActivityIds);
|
||||
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,12 +1,3 @@
|
||||
chill_asideactivities_controllers:
|
||||
resource: "@ChillAsideActivityBundle/Controller"
|
||||
type: annotation
|
||||
|
||||
chill_admin_aside_activity_redirect_to_admin_index:
|
||||
path: /{_locale}/admin/activity_redirect_to_main
|
||||
controller: Chill\ActivityBundle\Controller\AdminController::redirectToAdminIndexAction
|
||||
options:
|
||||
menus:
|
||||
admin_aside_activity:
|
||||
order: 0
|
||||
label: Main admin menu
|
||||
resource: "@ChillAsideActivityBundle/Controller"
|
||||
type: annotation
|
@@ -1,22 +1,8 @@
|
||||
services:
|
||||
Chill\AsideActivityBundle\DataFixtures\:
|
||||
resource: "./../DataFixtures"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Templating\Entity\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: "../Templating/Entity"
|
||||
tags:
|
||||
- "chill.render_entity"
|
||||
|
||||
Chill\AsideActivityBundle\Repository\:
|
||||
resource: "../Repository"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Controller\:
|
||||
resource: "../Controller"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
# services:
|
||||
# chill.asideactivity.form.type.asideactivity:
|
||||
# class: Chill\AsideActivityBundle\Form\AsideActivityFormType
|
||||
# arguments:
|
||||
# - "@chill.main.helper.translatable_string"
|
||||
# # - "%chill_activity.form.time_duration%"
|
||||
# tags:
|
||||
# - { name: form.type, alias: chill_asideactivitybundle_asideactivity }
|
@@ -1,6 +1,9 @@
|
||||
---
|
||||
services:
|
||||
Chill\AsideActivityBundle\Form\:
|
||||
resource: './../../Form'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
chill.asideactivity.form.type.asideactivity:
|
||||
class: Chill\AsideActivityBundle\Form\AsideActivityFormType
|
||||
arguments:
|
||||
- "@chill.main.helper.translatable_string"
|
||||
- "%chill_activity.form.time_duration%"
|
||||
tags:
|
||||
- { name: form.type, alias: chill_asideactivitybundle_asideactivity }
|
@@ -1,5 +0,0 @@
|
||||
services:
|
||||
Chill\AsideActivityBundle\Menu\:
|
||||
resource: "./../../Menu"
|
||||
autowire: true
|
||||
autoconfigure: true
|
@@ -7,11 +7,14 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210706124644 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Aside activity category entity created';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@@ -7,11 +7,14 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210804082249 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Aside activity entity created';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
@@ -56,12 +59,12 @@ final class Version20210804082249 extends AbstractMigration
|
||||
$this->addSql('CREATE INDEX idx_e9fa219165ff1aec ON asideactivity (updatedby_id)');
|
||||
$this->addSql('CREATE INDEX idx_e9fa21913414710b ON asideactivity (agent_id)');
|
||||
$this->addSql('COMMENT ON COLUMN asideactivity.updatedat IS \'(DC2Type:datetime_immutable)\'');
|
||||
$this->addSql('CREATE TABLE chill_main_address_legacy (id INT DEFAULT NULL, postcode_id INT DEFAULT NULL, street VARCHAR(255) DEFAULT NULL, streetnumber VARCHAR(255) DEFAULT NULL, validfrom DATE DEFAULT NULL, isnoaddress BOOLEAN DEFAULT NULL, customs JSONB DEFAULT NULL, floor VARCHAR(16) DEFAULT NULL, corridor VARCHAR(16) DEFAULT NULL, steps VARCHAR(16) DEFAULT NULL, buildingname VARCHAR(255) DEFAULT NULL, flat VARCHAR(16) DEFAULT NULL, distribution VARCHAR(255) DEFAULT NULL, extra VARCHAR(255) DEFAULT NULL, validto DATE DEFAULT NULL, point VARCHAR(255) DEFAULT NULL, linkedtothirdparty_id INT DEFAULT NULL)');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa2191c54c8c93 FOREIGN KEY (type_id) REFERENCES asideactivitytype (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa21913174800f FOREIGN KEY (createdby_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa219165ff1aec FOREIGN KEY (updatedby_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE asideactivity ADD CONSTRAINT fk_e9fa21913414710b FOREIGN KEY (agent_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('DROP TABLE chill_asideactivity.AsideActivity');
|
||||
$this->addSql('DROP TABLE chill_asideactivity.AsideActivityCategory');
|
||||
$this->addSql('DROP SCHEMA chill_asideactivity');
|
||||
}
|
||||
}
|
||||
|
@@ -7,11 +7,14 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210806140343 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Duration changed to type integer';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@@ -7,11 +7,14 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210806140710 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Duration changed back to timestamp';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@@ -7,11 +7,14 @@ namespace Chill\Migrations\AsideActivity;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20210810084456 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'createdat, updatedat and date given a type timestamp';
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
|
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\AsideActivity;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20210922182907 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Parent and children added to aside activity category entity';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD parent_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD CONSTRAINT FK_7BF90DBE727ACA70 FOREIGN KEY (parent_id) REFERENCES chill_asideactivity.AsideActivityCategory (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_7BF90DBE727ACA70 ON chill_asideactivity.asideactivitycategory (parent_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.AsideActivityCategory DROP parent');
|
||||
}
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\AsideActivity;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* allow to add an ordering to aside activity categories
|
||||
*/
|
||||
final class Version20211004134012 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'allow to add an ordering to aside activity categories';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory ADD ordering DOUBLE PRECISION NOT NULL DEFAULT 0.00');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_asideactivity.asideactivitycategory DROP ordering');
|
||||
}
|
||||
}
|
@@ -1,21 +1,23 @@
|
||||
#general
|
||||
Show the aside activity: Voir l'activité annexe
|
||||
Edit the aside activity: Modifier l'activité annexe
|
||||
Remove aside activity: Supprimer l'activité annexe
|
||||
Aside activity: Activité annexe
|
||||
Duration time: Durée
|
||||
durationTime: durée
|
||||
durationTime: durée
|
||||
user_username: nom de l'utilisateur
|
||||
Remark: Commentaire
|
||||
No comments: Aucun commentaire
|
||||
Add a new aside activity: Ajouter une nouvelle activité annexe
|
||||
Aside activity list: Activités annexes
|
||||
Aside activity list: Liste des activités annexes
|
||||
present: présent
|
||||
not present: absent
|
||||
Delete: Supprimer
|
||||
Update: Mettre à jour
|
||||
Update activity: Modifier l'activité
|
||||
Aside activity data: Données de l'activité annexe
|
||||
No reason associated: Aucun sujet
|
||||
There aren't any aside activities.: Aucune activité annexe enregistrée.
|
||||
type_name: type de l'activité
|
||||
Type: Type
|
||||
Invisible: Invisible
|
||||
Optional: Optionnel
|
||||
@@ -23,41 +25,32 @@ Required: Obligatoire
|
||||
Persons: Personnes
|
||||
Users: Utilisateurs
|
||||
Emergency: Urgent
|
||||
by: "Par "
|
||||
by: 'Par '
|
||||
location: Lieu
|
||||
|
||||
# Crud
|
||||
crud:
|
||||
aside_activity:
|
||||
title_view: Détail de l'activité annexe
|
||||
title_new: Nouvelle activité annexe
|
||||
title_edit: Édition d'une activité annexe
|
||||
title_delete: Supprimer une activité annexe
|
||||
title_new: Nouveau activité annexe
|
||||
title_edit: Edition d'une activité annexe
|
||||
title_delete: Supprimation d'une activité annexe
|
||||
button_delete: Supprimer
|
||||
confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
|
||||
confirm_message_delete: Êtes-vous sûr de vouloir supprimer cet activité annexe?
|
||||
aside_activity_category:
|
||||
title_new: Nouvelle catégorie d'activité annexe
|
||||
title_edit: Edition d'une catégorie de type d'activité
|
||||
|
||||
#forms
|
||||
Create a new aside activity type: Nouvelle categorie d'activité annexe
|
||||
Activity creation: Nouvelle activité annexe
|
||||
Create: Créer
|
||||
Back to the list: Retour à la liste
|
||||
Save activity: Sauver l'activité
|
||||
Reset form: Remise à zéro du formulaire
|
||||
Choose the agent for whom this activity is created: Choissisez l'agent pour qui l'activitée est creeé.
|
||||
Choose the activity category: Choissisez le type d'activité
|
||||
Choose the duration: Choisir la durée
|
||||
Choose a category: Choisir une catégorie
|
||||
Is active: Actif
|
||||
Agent: Utilisateur
|
||||
date: Date
|
||||
Duration: Durée
|
||||
Note: Note
|
||||
Choose the agent for whom this activity is created: Choisissez l'agent pour qui l'activité est créée
|
||||
Choose the activity category: Choisir la catégorie
|
||||
|
||||
#Duration
|
||||
minutes: minutes
|
||||
hour: heure
|
||||
hours: heures
|
||||
day: jour
|
||||
days: jours
|
||||
Choose a category: Choisir un categorie
|
||||
5 minutes: 5 minutes
|
||||
10 minutes: 10 minutes
|
||||
15 minutes: 15 minutes
|
||||
@@ -70,92 +63,14 @@ days: jours
|
||||
1 hour 30: 1 heure 30
|
||||
1 hour 45: 1 heure 45
|
||||
2 hours: 2 heures
|
||||
2 hours 30: 2 heure 30
|
||||
3 hours: 3 heures
|
||||
3 hours 30: 3 heure 30
|
||||
4 hours: 4 heures
|
||||
4 hours 30: 4 heure 30
|
||||
5 hours: 5 heures
|
||||
5 hours 30: 5 heure 30
|
||||
6 hours: 6 heures
|
||||
6 hours 30: 6 heure 30
|
||||
7 hours: 7 heures
|
||||
7 hours 30: 7 heure 30
|
||||
8 hours: 8 heures
|
||||
8 hours 30: 8 heure 30
|
||||
9 hours: 9 heures
|
||||
9 hours 30: 9 heure 30
|
||||
10 hours: 10 heures
|
||||
1/2 day: 1/2 jour
|
||||
1 day: 1 jour
|
||||
1 1/2 days: 1 1/2 jours
|
||||
2 days: 2 jours
|
||||
2 1/2 days: 2 1/2 jours
|
||||
3 days: 3 jours
|
||||
3 1/2 days: 3 1/2 jours
|
||||
4 days: 4 jours
|
||||
4 1/2 days: 4 1/2 jours
|
||||
5 days: 5 jours
|
||||
5 1/2 days: 5 1/2 jours
|
||||
6 days: 6 jours
|
||||
6 1/2 days: 6 1/2 jours
|
||||
7 days: 7 jours
|
||||
7 1/2 days: 7 1/2 jours
|
||||
8 days: 8 jours
|
||||
8 1/2 days: 8 1/2 jours
|
||||
9 days: 9 jours
|
||||
9 1/2 days: 9 1/2 jours
|
||||
10 days: 10 jours
|
||||
10 1/2 days: 10 1/2 jours
|
||||
11 days: 11 jours
|
||||
11 1/2 days: 11 1/2 jours
|
||||
12 days: 12 jours
|
||||
12 1/2 days: 12 1/2 jours
|
||||
13 days: 13 jours
|
||||
13 1/2 days: 13 1/2 jours
|
||||
14 days: 14 jours
|
||||
14 1/2 days: 14 1/2 jours
|
||||
15 days: 15 jours
|
||||
15 1/2 days: 15 1/2 jours
|
||||
16 days: 16 jours
|
||||
16 1/2 days: 16 1/2 jours
|
||||
17 days: 17 jours
|
||||
17 1/2 days: 17 1/2 jours
|
||||
18 days: 18 jours
|
||||
18 1/2 days: 18 1/2 jours
|
||||
19 days: 19 jours
|
||||
19 1/2 days: 19 1/2 jours
|
||||
20 days: 20 jours
|
||||
20 1/2 days: 20 1/2 jours
|
||||
21 days: 21 jours
|
||||
21 1/2 days: 21 1/2 jours
|
||||
22 days: 22 jours
|
||||
22 1/2 days: 22 1/2 jours
|
||||
23 days: 23 jours
|
||||
23 1/2 days: 23 1/2 jours
|
||||
24 days: 24 jours
|
||||
24 1/2 days: 24 1/2 jours
|
||||
25 days: 25 jours
|
||||
25 1/2 days: 25 1/2 jours
|
||||
26 days: 26 jours
|
||||
26 1/2 days: 26 1/2 jours
|
||||
27 days: 27 jours
|
||||
27 1/2 days: 27 1/2 jours
|
||||
28 days: 28 jours
|
||||
28 1/2 days: 28 1/2 jours
|
||||
29 days: 29 jours
|
||||
29 1/2 days: 29 1/2 jours
|
||||
30 days: 30 jours
|
||||
|
||||
#list
|
||||
My aside activities: Mes activités annexes
|
||||
Date: Date
|
||||
Created by: Creér par
|
||||
|
||||
|
||||
#Aside activity delete
|
||||
Delete aside activity: Supprimer une activité annexe
|
||||
Are you sure you want to remove the aside activity concerning "%name%" ?: Êtes-vous sûr de vouloir supprimer une activité annexe qui concerne "%name%" ?
|
||||
The activity has been successfully removed.: L'activité a été supprimée.
|
||||
|
||||
#Menu
|
||||
Create an aside activity: "Créer une activité annexe"
|
||||
Aside activity configuration menu: "Menu de configuration des activités annexes"
|
||||
Aside activity configuration: "Configuration des activités annexes"
|
||||
Phonecall: "Appel téléphonique"
|
||||
The activity has been successfully removed.: L'activité a été supprimée.
|
@@ -1 +0,0 @@
|
||||
You must not add twice the same category in the parent tree (previous result returned): Il est interdit d'indiquer la même entité dans l'arbre des parents. Le résultat précédent a été rétabli
|
@@ -36,9 +36,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\CalendarBundle\Form\CalendarType;
|
||||
use Chill\CalendarBundle\Repository\CalendarRepository;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
@@ -57,71 +55,54 @@ class CalendarController extends AbstractController
|
||||
|
||||
protected SerializerInterface $serializer;
|
||||
|
||||
protected PaginatorFactory $paginator;
|
||||
|
||||
private CalendarRepository $calendarRepository;
|
||||
|
||||
public function __construct(
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer,
|
||||
PaginatorFactory $paginator,
|
||||
CalendarRepository $calendarRepository
|
||||
SerializerInterface $serializer
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->logger = $logger;
|
||||
$this->serializer = $serializer;
|
||||
$this->paginator = $paginator;
|
||||
$this->calendarRepository = $calendarRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all Calendar entities.
|
||||
* @Route("/{_locale}/calendar/calendar/", name="chill_calendar_calendar_list")
|
||||
* @Route("/{_locale}/calendar/", name="chill_calendar_calendar")
|
||||
*/
|
||||
public function listAction(Request $request): Response
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$view = null;
|
||||
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($user instanceof User) {
|
||||
|
||||
$calendarItems = $this->calendarRepository->findByUser($user);
|
||||
|
||||
$view = '@ChillCalendar/Calendar/listByUser.html.twig';
|
||||
|
||||
return $this->render($view, [
|
||||
'calendarItems' => $calendarItems,
|
||||
'user' => $user
|
||||
]);
|
||||
// $calendar = $em->getRepository(Calendar::class)
|
||||
// ->findByUser($user)
|
||||
// ;
|
||||
|
||||
// $view = 'ChillCalendarBundle:Calendar:listByUser.html.twig';
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
|
||||
$total = $this->calendarRepository->countByAccompanyingPeriod($accompanyingPeriod);
|
||||
$paginator = $this->paginator->create($total);
|
||||
$calendarItems = $this->calendarRepository->findBy(
|
||||
['accompanyingPeriod' => $accompanyingPeriod],
|
||||
['startDate' => 'DESC'],
|
||||
$paginator->getItemsPerPage(),
|
||||
$paginator->getCurrentPageFirstItemNumber()
|
||||
$calendarItems = $em->getRepository(Calendar::class)->findBy(
|
||||
['accompanyingPeriod' => $accompanyingPeriod]
|
||||
);
|
||||
|
||||
$view = '@ChillCalendar/Calendar/listByAccompanyingCourse.html.twig';
|
||||
|
||||
return $this->render($view, [
|
||||
'calendarItems' => $calendarItems,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'paginator' => $paginator
|
||||
]);
|
||||
$view = 'ChillCalendarBundle:Calendar:listByAccompanyingCourse.html.twig';
|
||||
}
|
||||
|
||||
return $this->render($view, [
|
||||
'calendarItems' => $calendarItems,
|
||||
'user' => $user,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new calendar item
|
||||
* @Route("/{_locale}/calendar/calendar/new", name="chill_calendar_calendar_new")
|
||||
* @Route("/{_locale}/calendar/new", name="chill_calendar_calendar_new")
|
||||
*/
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
@@ -130,10 +111,10 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/newByAccompanyingCourse.html.twig';
|
||||
$view = 'ChillCalendarBundle:Calendar:newAccompanyingCourse.html.twig';
|
||||
}
|
||||
// elseif ($user instanceof User) {
|
||||
// $view = '@ChillCalendar/Calendar/newUser.html.twig';
|
||||
// $view = 'ChillCalendarBundle:Calendar:newUser.html.twig';
|
||||
// }
|
||||
|
||||
$entity = new Calendar();
|
||||
@@ -160,7 +141,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
@@ -183,7 +164,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Show a calendar item
|
||||
* @Route("/{_locale}/calendar/calendar/{id}/show", name="chill_calendar_calendar_show")
|
||||
* @Route("/{_locale}/calendar/{id}/show", name="chill_calendar_calendar_show")
|
||||
*/
|
||||
public function showAction(Request $request, $id): Response
|
||||
{
|
||||
@@ -192,11 +173,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/showByAccompanyingCourse.html.twig';
|
||||
$view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig';
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/showByUser.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig';
|
||||
// }
|
||||
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
@@ -215,33 +196,10 @@ class CalendarController extends AbstractController
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
$personsId = [];
|
||||
foreach ($entity->getPersons() as $p) {
|
||||
array_push($personsId, $p->getId());
|
||||
}
|
||||
|
||||
$professionalsId = [];
|
||||
foreach ($entity->getProfessionals() as $p) {
|
||||
array_push($professionalsId, $p->getId());
|
||||
}
|
||||
|
||||
$durationTime = $entity->getEndDate()->diff($entity->getStartDate());
|
||||
$durationTimeInMinutes = $durationTime->days*1440 + $durationTime->h*60 + $durationTime->i;
|
||||
|
||||
$activityData = [
|
||||
'calendarId' => $id,
|
||||
'personsId' => $personsId,
|
||||
'professionalsId' => $professionalsId,
|
||||
'date' => $entity->getStartDate()->format('Y-m-d'),
|
||||
'durationTime' => $durationTimeInMinutes,
|
||||
'comment' => $entity->getComment()->getComment(),
|
||||
];
|
||||
|
||||
return $this->render($view, [
|
||||
//'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'entity' => $entity,
|
||||
'user' => $user,
|
||||
'activityData' => $activityData
|
||||
//'delete_form' => $deleteForm->createView(),
|
||||
]);
|
||||
}
|
||||
@@ -250,7 +208,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Edit a calendar item
|
||||
* @Route("/{_locale}/calendar/calendar/{id}/edit", name="chill_calendar_calendar_edit")
|
||||
* @Route("/{_locale}/calendar/{id}/edit", name="chill_calendar_calendar_edit")
|
||||
*/
|
||||
public function editAction($id, Request $request): Response
|
||||
{
|
||||
@@ -259,11 +217,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/editByAccompanyingCourse.html.twig';
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/editByUser.html.twig';
|
||||
$view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig';
|
||||
// }
|
||||
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
@@ -282,7 +240,7 @@ class CalendarController extends AbstractController
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : calendar item updated!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
@@ -300,7 +258,6 @@ class CalendarController extends AbstractController
|
||||
'form' => $form->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'user' => $user,
|
||||
'entity_json' => $entity_array
|
||||
]);
|
||||
}
|
||||
@@ -316,11 +273,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByAccompanyingCourse.html.twig';
|
||||
$view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig';
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByUser.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig';
|
||||
// }
|
||||
|
||||
/* @var $entity Calendar */
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
@@ -348,7 +305,7 @@ class CalendarController extends AbstractController
|
||||
->trans("The calendar item has been successfully removed."));
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,9 +323,9 @@ class CalendarController extends AbstractController
|
||||
/**
|
||||
* Creates a form to delete a Calendar entity by id.
|
||||
*/
|
||||
private function createDeleteForm(int $id, ?User $user, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
{
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
$params['id'] = $id;
|
||||
|
||||
return $this->createFormBuilder()
|
||||
@@ -392,8 +349,7 @@ class CalendarController extends AbstractController
|
||||
throw $this->createNotFoundException('User not found');
|
||||
}
|
||||
|
||||
// TODO Add permission
|
||||
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user);
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user);
|
||||
} elseif ($request->query->has('accompanying_period_id')) {
|
||||
$accompanying_period_id = $request->get('accompanying_period_id');
|
||||
$accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id);
|
||||
|
@@ -18,20 +18,17 @@ class CalendarRangeAPIController extends ApiController
|
||||
*/
|
||||
public function availableRanges(Request $request, string $_format): JsonResponse
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$sql = 'SELECT c FROM ChillCalendarBundle:CalendarRange c
|
||||
WHERE NOT EXISTS (SELECT cal.id FROM ChillCalendarBundle:Calendar cal WHERE cal.calendarRange = c.id)';
|
||||
|
||||
if ($request->query->has('user')) {
|
||||
$user = $request->query->get('user');
|
||||
$sql = $sql . ' AND c.user = :user';
|
||||
$query = $em->createQuery($sql)
|
||||
->setParameter('user', $user);
|
||||
} else {
|
||||
$query = $em->createQuery($sql);
|
||||
}
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$query = $em->createQuery(
|
||||
'SELECT c FROM ChillCalendarBundle:CalendarRange c
|
||||
WHERE NOT EXISTS (SELECT cal.id FROM ChillCalendarBundle:Calendar cal WHERE cal.calendarRange = c.id)')
|
||||
;
|
||||
|
||||
$results = $query->getResult();
|
||||
|
||||
return $this->json(['count' => count($results), 'results' => $results], Response::HTTP_OK, [], [ 'groups' => [ 'read' ]]);
|
||||
|
@@ -29,7 +29,6 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf
|
||||
$loader->load('services/controller.yml');
|
||||
$loader->load('services/fixtures.yml');
|
||||
$loader->load('services/form.yml');
|
||||
$loader->load('services/event.yml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
@@ -67,16 +66,13 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true,
|
||||
Request::METHOD_HEAD => true
|
||||
],
|
||||
],
|
||||
'_entity' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true,
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_PATCH => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
Request::METHOD_HEAD => true
|
||||
]
|
||||
],
|
||||
]
|
||||
|
@@ -37,16 +37,14 @@ class Calendar
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private ?int $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private ?User $user = null;
|
||||
private User $user;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
|
||||
@@ -66,7 +64,6 @@ class Calendar
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\JoinTable(name="chill_calendar.calendar_to_persons")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private Collection $persons;
|
||||
|
||||
@@ -77,7 +74,6 @@ class Calendar
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private Collection $professionals;
|
||||
|
||||
@@ -93,7 +89,6 @@ class Calendar
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private CommentEmbeddable $comment;
|
||||
|
||||
@@ -101,20 +96,20 @@ class Calendar
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private ?\DateTimeImmutable $startDate = null;
|
||||
private \DateTimeImmutable $startDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private ?\DateTimeImmutable $endDate = null;
|
||||
private \DateTimeImmutable $endDate;
|
||||
|
||||
//TODO Lieu
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private ?string $status = null;
|
||||
private string $status;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="CancelReason")
|
||||
@@ -129,7 +124,7 @@ class Calendar
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\Activity")
|
||||
*/
|
||||
private ?Activity $activity = null;
|
||||
private Activity $activity;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
|
@@ -25,21 +25,21 @@ class CalendarRange
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
* @groups({"read", "write"})
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private ?User $user = null;
|
||||
private User $user;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @groups({"read", "write"})
|
||||
* @groups({"read"})
|
||||
*/
|
||||
private ?\DateTimeImmutable $startDate = null;
|
||||
private \DateTimeImmutable $startDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @groups({"read", "write"})
|
||||
* @groups({"read"})
|
||||
*/
|
||||
private ?\DateTimeImmutable $endDate = null;
|
||||
private \DateTimeImmutable $endDate;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Calendar::class,
|
||||
|
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CalendarBundle\Event;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class ListenToActivityCreate
|
||||
{
|
||||
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function postPersist(Activity $activity, LifecycleEventArgs $event): void
|
||||
{
|
||||
// Get the calendarId from the request
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
|
||||
if (null === $request) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
if (array_key_exists('calendarId', $activityData)) {
|
||||
$calendarId = $activityData['calendarId'];
|
||||
|
||||
// Attach the activity to the calendar
|
||||
$em = $event->getObjectManager();
|
||||
|
||||
$calendar = $em->getRepository(\Chill\CalendarBundle\Entity\Calendar::class)->find($calendarId);
|
||||
$calendar->setActivity($activity);
|
||||
|
||||
$em->persist($calendar);
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -36,12 +36,12 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
$period = $parameters['accompanyingCourse'];
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
|
||||
$menu->addChild($this->translator->trans('Calendar'), [
|
||||
'route' => 'chill_calendar_calendar_list',
|
||||
$menu->addChild($this->translator->trans('Calendar list'), [
|
||||
'route' => 'chill_calendar_calendar',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
]])
|
||||
->setExtras(['order' => 35]);
|
||||
->setExtras(['order' => 41]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,9 +3,7 @@
|
||||
namespace Chill\CalendarBundle\Repository;
|
||||
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
@@ -16,13 +14,9 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
*/
|
||||
class CalendarRepository extends ServiceEntityRepository
|
||||
{
|
||||
|
||||
// private EntityRepository $repository;
|
||||
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Calendar::class);
|
||||
// $this->repository = $entityManager->getRepository(AccompanyingPeriodWork::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
|
@@ -1,10 +0,0 @@
|
||||
services:
|
||||
Chill\CalendarBundle\Event\ListenToActivityCreate:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
tags:
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'postPersist'
|
||||
entity: 'Chill\ActivityBundle\Entity\Activity'
|
||||
|
@@ -7,14 +7,4 @@ div#calendarControls {
|
||||
|
||||
div#fullCalendar{
|
||||
|
||||
}
|
||||
|
||||
span.calendarRangeItems {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
a {
|
||||
text-decoration: none;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
@@ -6,15 +6,13 @@
|
||||
v-bind:calendarEvents="calendarEvents"
|
||||
v-bind:updateEventsSource="updateEventsSource"
|
||||
v-bind:showMyCalendar="showMyCalendar"
|
||||
v-bind:toggleMyCalendar="toggleMyCalendar"
|
||||
v-bind:toggleWeekends="toggleWeekends" >
|
||||
v-bind:toggleMyCalendar="toggleMyCalendar" >
|
||||
</calendar-user-selector>
|
||||
</teleport>
|
||||
<teleport to="#fullCalendar">
|
||||
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
||||
<template v-slot:eventContent='arg'>
|
||||
<b>{{ arg.timeText }}</b>
|
||||
<i> {{ arg.event.title }}</i>
|
||||
</template>
|
||||
</FullCalendar>
|
||||
</teleport>
|
||||
@@ -23,13 +21,22 @@
|
||||
<script>
|
||||
import ConcernedGroups from 'ChillActivityAssets/vuejs/Activity/components/ConcernedGroups.vue';
|
||||
import CalendarUserSelector from '../_components/CalendarUserSelector/CalendarUserSelector.vue';
|
||||
import '@fullcalendar/core/vdom'; // solves problem with Vite
|
||||
import '@fullcalendar/core/vdom' // solves problem with Vite
|
||||
import frLocale from '@fullcalendar/core/locales/fr';
|
||||
import FullCalendar from '@fullcalendar/vue3';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import interactionPlugin from '@fullcalendar/interaction';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
// import listPlugin from '@fullcalendar/list';
|
||||
import FullCalendar from '@fullcalendar/vue3'
|
||||
import dayGridPlugin from '@fullcalendar/daygrid'
|
||||
import interactionPlugin from '@fullcalendar/interaction'
|
||||
import timeGridPlugin from '@fullcalendar/timegrid'
|
||||
import listPlugin from '@fullcalendar/list';
|
||||
|
||||
const currentEvent = {
|
||||
events: [{
|
||||
title: 'my_event',
|
||||
start: window.startDate,
|
||||
end: window.endDate
|
||||
}],
|
||||
id: window.mainUser
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
@@ -50,23 +57,12 @@ export default {
|
||||
loaded: [],
|
||||
selected: [],
|
||||
user: [],
|
||||
current: {
|
||||
events: [{
|
||||
title: 'plage prévue',
|
||||
start: window.startDate,
|
||||
end: window.endDate
|
||||
}],
|
||||
id: window.mainUser,
|
||||
color: '#bbbbbb'
|
||||
}
|
||||
current: currentEvent
|
||||
},
|
||||
selectedEvent: null,
|
||||
previousSelectedEvent: null,
|
||||
previousSelectedEventColor: null,
|
||||
showMyCalendar: false,
|
||||
showMyCalendar: true,
|
||||
calendarOptions: {
|
||||
locale: frLocale,
|
||||
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ],
|
||||
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin, listPlugin ],
|
||||
initialView: 'timeGridWeek',
|
||||
initialDate: window.startDate !== undefined ? window.startDate : new Date(),
|
||||
eventSource: [],
|
||||
@@ -78,7 +74,6 @@ export default {
|
||||
// eventMouseLeave: this.onEventMouseLeave,
|
||||
selectMirror: true,
|
||||
editable: true,
|
||||
weekends: false,
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
@@ -89,54 +84,36 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.updateEventsSource();
|
||||
console.log(window.startDate)
|
||||
this.updateEventsSource()
|
||||
},
|
||||
toggleMyCalendar(value) {
|
||||
this.showMyCalendar = value;
|
||||
},
|
||||
toggleWeekends: function() {
|
||||
this.calendarOptions.weekends = !this.calendarOptions.weekends;
|
||||
},
|
||||
updateEventsSource() {
|
||||
this.calendarOptions.eventSources = [];
|
||||
this.calendarOptions.eventSources.push(...this.calendarEvents.selected);
|
||||
console.log(this.calendarOptions.eventSources)
|
||||
if (window.startDate !== undefined) {
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.current);
|
||||
this.calendarOptions.eventSources.push(currentEvent);
|
||||
}
|
||||
if (this.showMyCalendar) {
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.user);
|
||||
}
|
||||
},
|
||||
unSelectPreviousEvent(event) {
|
||||
if (event) {
|
||||
if (typeof event.setProp === 'function') {
|
||||
event.setProp('backgroundColor', this.previousSelectedEventColor);
|
||||
event.setProp('borderColor', this.previousSelectedEventColor);
|
||||
event.setProp('textColor','#444444');
|
||||
event.setProp('title','');
|
||||
}
|
||||
}
|
||||
console.log(this.calendarOptions.eventSources)
|
||||
},
|
||||
onDateSelect(payload) {
|
||||
console.log(payload)
|
||||
this.unSelectPreviousEvent(this.selectedEvent);
|
||||
Object.assign(payload, {users: this.users});
|
||||
Object.assign(payload, {title: 'Choisir cette plage'}); //TODO does not display
|
||||
//payload.event.setProp('title', 'Choisir cette plage');
|
||||
this.$store.dispatch('createEvent', payload);
|
||||
},
|
||||
onEventChange(payload) {
|
||||
console.log(this.calendarOptions.eventSources)
|
||||
this.$store.dispatch('updateEvent', payload);
|
||||
},
|
||||
onEventClick(payload) {
|
||||
this.previousSelectedEvent = this.selectedEvent;
|
||||
this.previousSelectedEventColor = payload.event.extendedProps.sourceColor;
|
||||
this.selectedEvent = payload.event;
|
||||
this.unSelectPreviousEvent(this.previousSelectedEvent);
|
||||
payload.event.setProp('backgroundColor','#3788d8');
|
||||
payload.event.setProp('borderColor','#3788d8');
|
||||
payload.event.setProp('title', 'Choisir cette plage');
|
||||
payload.event.setProp('textColor','#ffffff');
|
||||
//this.$store.dispatch('updateEvent', payload);
|
||||
},
|
||||
onEventMouseEnter(payload) {
|
||||
payload.event.setProp('borderColor','#444444');
|
||||
|
@@ -1,468 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="chill-red">{{ $t('edit_your_calendar_range') }}</h2>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="myCalendar" class="form-check-input" v-model="showMyCalendarWidget" />
|
||||
<label class="form-check-label" for="myCalendar">{{ $t('show_my_calendar') }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="weekends" class="form-check-input" @click="toggleWeekends" />
|
||||
<label class="form-check-label" for="weekends">{{ $t('show_weekends') }}</label>
|
||||
</div>
|
||||
|
||||
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
||||
<template v-slot:eventContent='arg' >
|
||||
<span class='calendarRangeItems'>
|
||||
<b v-if="arg.event.extendedProps.myCalendar" style="text-decoration: underline" >{{ arg.timeText }}</b>
|
||||
<b v-else-if="!arg.event.extendedProps.myCalendar && arg.event.extendedProps.toDelete" style="text-decoration: line-through red" >{{ arg.timeText }}</b>
|
||||
<b v-else >{{ arg.timeText }}</b>
|
||||
<i> {{ arg.event.title }}</i>
|
||||
<a v-if=!arg.event.extendedProps.myCalendar class="fa fa-fw fa-times"
|
||||
@click.prevent="onClickDelete(arg.event)">
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</FullCalendar>
|
||||
<div>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="btn btn-save" :disabled="!dirty"
|
||||
@click.prevent="onClickSave">
|
||||
{{ $t('action.save')}}
|
||||
</button>
|
||||
<span v-if="flag.loading" class="loading">
|
||||
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i>
|
||||
<span class="sr-only">{{ $t('loading') }}</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<button v-if="disableCopyDayButton" class="btn btn-action" disabled>
|
||||
{{ $t('copy_range_to_next_day')}}
|
||||
</button>
|
||||
<button v-else class="btn btn-action"
|
||||
@click.prevent="copyDay">
|
||||
{{ $t('copy_range_from_day')}} {{this.lastNewDate.toLocaleDateString()}} {{ $t('to_the_next_day')}}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="newCalendarRanges.length > 0">
|
||||
<h4>{{ $t('new_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in newCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="updateCalendarRanges.length > 0">
|
||||
<h4>{{ $t('update_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in updateCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="deleteCalendarRanges.length > 0">
|
||||
<h4>{{ $t('delete_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in deleteCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal.showModal"
|
||||
:modalDialogClass="modal.modalDialogClass"
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<template v-slot:header>
|
||||
<h2 class="modal-title">{{ this.renderEventDate() }}</h2>
|
||||
</template>
|
||||
|
||||
<template v-slot:body>
|
||||
<p>{{ $t('by')}} {{this.myCalendarClickedEvent.user.username }}</p>
|
||||
<p>{{ $t('main_user_concerned') }} : {{ this.myCalendarClickedEvent.mainUser.username }}</p>
|
||||
<p v-if="myCalendarClickedEvent.comment.length > 0" >{{ this.myCalendarClickedEvent.comment }}</p>
|
||||
</template>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-show"
|
||||
:href=myCalendarEventShowLink() >
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-update"
|
||||
:href=myCalendarEventUpdateLink() >
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-delete"
|
||||
:href=myCalendarEventDeleteLink() >
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import '@fullcalendar/core/vdom'; // solves problem with Vite
|
||||
import frLocale from '@fullcalendar/core/locales/fr';
|
||||
import FullCalendar from '@fullcalendar/vue3';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import interactionPlugin from '@fullcalendar/interaction';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
import { deleteCalendarRange, fetchCalendar, fetchCalendarRangesByUser, patchCalendarRange, postCalendarRange } from '../_api/api';
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
FullCalendar,
|
||||
Modal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
errorMsg: [],
|
||||
modal: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-m"
|
||||
},
|
||||
flag: {
|
||||
loading: false
|
||||
},
|
||||
userId: window.userId,
|
||||
showMyCalendar: true,
|
||||
myCalendarClickedEvent: null,
|
||||
calendarEvents: {
|
||||
userCalendar: null,
|
||||
userCalendarRange: null,
|
||||
new: {
|
||||
events: [],
|
||||
color: "#3788d8"
|
||||
}
|
||||
},
|
||||
lastNewDate: null,
|
||||
disableCopyDayButton: true,
|
||||
calendarOptions: {
|
||||
locale: frLocale,
|
||||
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ],
|
||||
initialView: 'timeGridWeek',
|
||||
initialDate: window.startDate !== undefined ? window.startDate : new Date(),
|
||||
eventSource: [],
|
||||
selectable: true,
|
||||
select: this.onDateSelect,
|
||||
eventChange: this.onEventChange,
|
||||
eventDrop: this.onEventDropOrResize,
|
||||
eventResize: this.onEventDropOrResize,
|
||||
eventClick: this.onEventClick,
|
||||
selectMirror: false,
|
||||
editable: true,
|
||||
weekends: false,
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
newCalendarRanges: state => state.newCalendarRanges,
|
||||
updateCalendarRanges: state => state.updateCalendarRanges,
|
||||
deleteCalendarRanges: state => state.deleteCalendarRanges,
|
||||
dirty: state => state.newCalendarRanges.length > 0 || state.updateCalendarRanges.length > 0 || state.deleteCalendarRanges.length > 0
|
||||
}),
|
||||
showMyCalendarWidget: {
|
||||
set(value) {
|
||||
this.toggleMyCalendar(value);
|
||||
this.updateEventsSource();
|
||||
},
|
||||
get() {
|
||||
return this.showMyCalendar;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.fetchData();
|
||||
},
|
||||
openModal() {
|
||||
this.modal.showModal = true;
|
||||
},
|
||||
myCalendarEventShowLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/show?user_id=${ this.userId }`
|
||||
},
|
||||
myCalendarEventUpdateLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/edit?user_id=${ this.userId }`
|
||||
},
|
||||
myCalendarEventDeleteLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/delete?user_id=${ this.userId }`
|
||||
},
|
||||
resetCalendar() {
|
||||
this.fetchData();
|
||||
this.calendarEvents.new = {
|
||||
events: [],
|
||||
color: "#3788d8"
|
||||
};
|
||||
this.updateEventsSource();
|
||||
},
|
||||
fetchData() {
|
||||
this.flag.loading = true;
|
||||
fetchCalendarRangesByUser(this.userId).then(calendarRanges => new Promise((resolve, reject) => {
|
||||
let events = calendarRanges.results.map(i =>
|
||||
({
|
||||
start: i.startDate.datetime,
|
||||
end: i.endDate.datetime,
|
||||
calendarRangeId: i.id,
|
||||
toDelete: false
|
||||
})
|
||||
);
|
||||
let calendarRangeEvents = {
|
||||
events: events,
|
||||
borderColor: "#3788d8",
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#444444',
|
||||
};
|
||||
this.calendarEvents.userCalendarRange = calendarRangeEvents;
|
||||
|
||||
fetchCalendar(this.userId).then(calendar => new Promise((resolve, reject) => {
|
||||
let events = calendar.results.map(i =>
|
||||
({
|
||||
myCalendar: true,
|
||||
calendarId: i.id,
|
||||
start: i.startDate.datetime,
|
||||
end: i.endDate.datetime,
|
||||
user: i.user,
|
||||
mainUser: i.mainUser,
|
||||
persons: i.persons,
|
||||
professionals: i.professionals,
|
||||
comment: i.comment
|
||||
})
|
||||
);
|
||||
let calendarEventsCurrentUser = {
|
||||
events: events,
|
||||
color: 'darkblue',
|
||||
id: 1000,
|
||||
editable: false
|
||||
};
|
||||
this.calendarEvents.userCalendar = calendarEventsCurrentUser;
|
||||
this.updateEventsSource();
|
||||
this.flag.loading = false;
|
||||
resolve();
|
||||
}));
|
||||
|
||||
resolve();
|
||||
}));
|
||||
},
|
||||
updateEventsSource() {
|
||||
this.calendarOptions.eventSources = [];
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.new);
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendarRange);
|
||||
if (this.showMyCalendar) {
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendar);
|
||||
}
|
||||
console.log(this.calendarOptions.eventSources);
|
||||
},
|
||||
toggleMyCalendar(value) {
|
||||
this.showMyCalendar = value;
|
||||
},
|
||||
toggleWeekends: function() {
|
||||
this.calendarOptions.weekends = !this.calendarOptions.weekends;
|
||||
},
|
||||
onDateSelect(payload) {
|
||||
let events = this.calendarEvents.new.events;
|
||||
events.push({
|
||||
start: payload.startStr,
|
||||
end: payload.endStr
|
||||
});
|
||||
this.calendarEvents.new = {
|
||||
events: events,
|
||||
borderColor: "#3788d8",
|
||||
backgroundColor: '#fffadf ',
|
||||
textColor: '#444444',
|
||||
};
|
||||
this.disableCopyDayButton = false;
|
||||
this.lastNewDate = new Date(payload.startStr);
|
||||
this.updateEventsSource();
|
||||
this.$store.dispatch('createRange', payload);
|
||||
},
|
||||
onEventChange(payload) {
|
||||
},
|
||||
onEventDropOrResize(payload) {
|
||||
payload.event.setProp('borderColor', '#3788d8');
|
||||
payload.event.setProp('backgroundColor', '#fffadf');
|
||||
payload.event.setProp('textColor', '#444444');
|
||||
this.$store.dispatch('updateRange', payload);
|
||||
},
|
||||
onEventClick(payload) {
|
||||
if (payload.event.extendedProps.myCalendar) {
|
||||
this.myCalendarClickedEvent = {
|
||||
id: payload.event.extendedProps.calendarId,
|
||||
start: payload.event.start,
|
||||
end: payload.event.end,
|
||||
user: payload.event.extendedProps.user,
|
||||
mainUser: payload.event.extendedProps.mainUser,
|
||||
persons: payload.event.extendedProps.persons,
|
||||
professionals: payload.event.extendedProps.professionals,
|
||||
comment: payload.event.extendedProps.comment
|
||||
};
|
||||
console.log(this.myCalendarClickedEvent)
|
||||
this.openModal();
|
||||
}
|
||||
},
|
||||
onClickSave(payload) {
|
||||
this.flag.loading = true;
|
||||
if (this.$store.state.newCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.newCalendarRanges.map(cr => {
|
||||
postCalendarRange({
|
||||
user: {
|
||||
type: 'user',
|
||||
id: window.userId,
|
||||
},
|
||||
startDate: {
|
||||
datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
||||
},
|
||||
endDate: {
|
||||
datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
||||
},
|
||||
})
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
|
||||
this.$store.dispatch('clearNewCalendarRanges', payload);
|
||||
}
|
||||
if (this.$store.state.updateCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.updateCalendarRanges.map(cr => {
|
||||
patchCalendarRange(cr.id,
|
||||
{
|
||||
startDate: {
|
||||
datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
||||
},
|
||||
endDate: {
|
||||
datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
||||
},
|
||||
})
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
this.$store.dispatch('clearUpdateCalendarRanges', payload);
|
||||
}
|
||||
if (this.$store.state.deleteCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.deleteCalendarRanges.map(cr => {
|
||||
deleteCalendarRange(cr.id)
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
this.$store.dispatch('clearDeleteCalendarRanges', payload);
|
||||
}
|
||||
|
||||
},
|
||||
onClickDelete(payload) {
|
||||
if (payload.extendedProps.hasOwnProperty("calendarRangeId")) {
|
||||
if (payload.extendedProps.toDelete) {
|
||||
payload.setExtendedProp('toDelete', false)
|
||||
payload.setProp('borderColor', '#79bafc');
|
||||
this.$store.dispatch('removeFromDeleteRange', payload);
|
||||
} else {
|
||||
payload.setExtendedProp('toDelete', true)
|
||||
payload.setProp('borderColor', '#dddddd');
|
||||
this.$store.dispatch('deleteRange', payload);
|
||||
}
|
||||
} else {
|
||||
let newEvents = this.calendarEvents.new.events;
|
||||
let filterEvents = newEvents.filter((e) =>
|
||||
e.start !== payload.startStr && e.end !== payload.endStr
|
||||
);
|
||||
this.calendarEvents.new = {
|
||||
events: filterEvents,
|
||||
color: "#3788d8"
|
||||
};
|
||||
|
||||
this.$store.dispatch('removeNewCalendarRanges', payload);
|
||||
|
||||
this.updateEventsSource();
|
||||
}
|
||||
|
||||
},
|
||||
isSameDay(date1, date2) {
|
||||
return date1.getFullYear() === date2.getFullYear() &&
|
||||
date1.getMonth() === date2.getMonth() &&
|
||||
date1.getDate() === date2.getDate();
|
||||
},
|
||||
isFriday(date) {
|
||||
return date.getDay() === 5
|
||||
},
|
||||
copyDay(_payload) {
|
||||
console.log(this.calendarEvents.new);
|
||||
if (this.calendarEvents.new.events.length > 0) {
|
||||
// Create the copied events
|
||||
let increment = !this.calendarOptions.weekends && this.isFriday(this.lastNewDate) ? 24*60*60*1000*3 : 24*60*60*1000;
|
||||
let events = this.calendarEvents.new.events.filter(
|
||||
i => this.isSameDay(new Date(i.start), this.lastNewDate)).map(
|
||||
i => {
|
||||
let startDate = new Date(new Date(i.start).getTime() + increment);
|
||||
let endDate = new Date(new Date(i.end).getTime() + increment);
|
||||
return ({
|
||||
start: startDate.toISOString(),
|
||||
end: endDate.toISOString()
|
||||
})
|
||||
}
|
||||
);
|
||||
let copiedEvents = {
|
||||
events: events,
|
||||
color: "#3788d8"
|
||||
};
|
||||
console.log(copiedEvents);
|
||||
|
||||
// Add to the calendar
|
||||
let newEvents = this.calendarEvents.new.events;
|
||||
newEvents.push(...copiedEvents.events);
|
||||
this.calendarEvents.new = {
|
||||
events: newEvents,
|
||||
color: "#3788d8"
|
||||
};
|
||||
this.updateEventsSource();
|
||||
|
||||
// Set the last new date
|
||||
this.lastNewDate = new Date(copiedEvents.events[copiedEvents.events.length - 1].start);
|
||||
|
||||
// Dispatch in store for saving
|
||||
for (let i = 0; i < copiedEvents.events.length; i++) {
|
||||
let eventObj = {
|
||||
start: new Date(copiedEvents.events[i].start),
|
||||
end: new Date(copiedEvents.events[i].end)
|
||||
}
|
||||
this.$store.dispatch('createRange', eventObj);
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log('no new events to copy-paste!')
|
||||
}
|
||||
},
|
||||
renderEventDate() {
|
||||
let start = this.myCalendarClickedEvent.start;
|
||||
let end = this.myCalendarClickedEvent.end;
|
||||
return start.getDate() === end.getDate() ?
|
||||
`${start.toLocaleDateString()}, ${start.toLocaleTimeString()} - ${end.toLocaleTimeString()}` :
|
||||
`${start.toLocaleString()} - ${end.toLocaleString()}`;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -1,21 +0,0 @@
|
||||
const appMessages = {
|
||||
fr: {
|
||||
edit_your_calendar_range: "Planifiez vos plages de disponibilités",
|
||||
show_my_calendar: "Afficher mon calendrier",
|
||||
show_weekends: "Afficher les week-ends",
|
||||
copy_range_to_next_day: "Copier les plages du jour au jour suivant",
|
||||
copy_range_from_day: "Copier les plages du ",
|
||||
to_the_next_day: " au jour suivant",
|
||||
copy_range_to_next_week: "Copier les plages de la semaine à la semaine suivante",
|
||||
copy_range_how_to: "Créez les plages de disponibilités durant une journée et copiez-les facilement au jour suivant avec ce bouton. Si les week-ends sont cachés, le jour suivant un vendredi sera le lundi.",
|
||||
new_range_to_save: "Nouvelles plages à enregistrer",
|
||||
update_range_to_save: "Plages à modifier",
|
||||
delete_range_to_save: "Plages à supprimer",
|
||||
by: "Par",
|
||||
main_user_concerned: "Utilisateur concerné"
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
appMessages
|
||||
};
|
@@ -1,16 +0,0 @@
|
||||
import { createApp } from 'vue';
|
||||
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
|
||||
import { appMessages } from './i18n'
|
||||
import store from './store'
|
||||
|
||||
import App from './App.vue';
|
||||
|
||||
const i18n = _createI18n(appMessages);
|
||||
|
||||
const app = createApp({
|
||||
template: `<app></app>`,
|
||||
})
|
||||
.use(store)
|
||||
.use(i18n)
|
||||
.component('app', App)
|
||||
.mount('#myCalendar');
|
@@ -1,89 +0,0 @@
|
||||
import 'es6-promise/auto';
|
||||
import { createStore } from 'vuex';
|
||||
import { postCalendarRange, patchCalendarRange, deleteCalendarRange } from '../_api/api';
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const store = createStore({
|
||||
strict: debug,
|
||||
state: {
|
||||
newCalendarRanges: [],
|
||||
updateCalendarRanges: [],
|
||||
deleteCalendarRanges: []
|
||||
},
|
||||
mutations: {
|
||||
updateRange(state, payload) {
|
||||
state.updateCalendarRanges.push({
|
||||
id: payload.event.extendedProps.calendarRangeId,
|
||||
start: payload.event.start,
|
||||
end: payload.event.end
|
||||
});
|
||||
},
|
||||
addRange(state, payload) {
|
||||
state.newCalendarRanges.push({
|
||||
start: payload.start,
|
||||
end: payload.end
|
||||
});
|
||||
},
|
||||
deleteRange(state, payload) {
|
||||
state.deleteCalendarRanges.push({
|
||||
id: payload.extendedProps.calendarRangeId,
|
||||
start: payload.start,
|
||||
end: payload.end
|
||||
});
|
||||
},
|
||||
clearNewCalendarRanges(state) {
|
||||
state.newCalendarRanges = [];
|
||||
},
|
||||
clearUpdateCalendarRanges(state) {
|
||||
state.updateCalendarRanges = [];
|
||||
},
|
||||
clearDeleteCalendarRanges(state) {
|
||||
state.deleteCalendarRanges = [];
|
||||
},
|
||||
removeNewCalendarRanges(state, payload) {
|
||||
let filteredCollection = state.newCalendarRanges.filter(
|
||||
(e) => e.start.toString() !== payload.start.toString() && e.end.toString() !== payload.end.toString()
|
||||
)
|
||||
state.newCalendarRanges = filteredCollection;
|
||||
},
|
||||
removeFromDeleteRange(state, payload) {
|
||||
let filteredCollection = state.deleteCalendarRanges.filter(
|
||||
(e) => e.start.toString() !== payload.start.toString() && e.end.toString() !== payload.end.toString()
|
||||
)
|
||||
state.deleteCalendarRanges = filteredCollection;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
createRange({ commit }, payload) {
|
||||
console.log('### action createRange', payload);
|
||||
commit('addRange', payload);
|
||||
},
|
||||
updateRange({ commit }, payload) {
|
||||
console.log('### action updateRange', payload);
|
||||
commit('updateRange', payload);
|
||||
},
|
||||
deleteRange({ commit }, payload) {
|
||||
console.log('### action deleteRange', payload);
|
||||
commit('deleteRange', payload);
|
||||
},
|
||||
clearNewCalendarRanges({ commit }, payload) {
|
||||
commit('clearNewCalendarRanges', payload);
|
||||
},
|
||||
clearUpdateCalendarRanges({ commit }, payload) {
|
||||
commit('clearUpdateCalendarRanges', payload);
|
||||
},
|
||||
clearDeleteCalendarRanges({ commit }, payload) {
|
||||
commit('clearDeleteCalendarRanges', payload);
|
||||
},
|
||||
removeNewCalendarRanges({ commit }, payload) {
|
||||
commit('removeNewCalendarRanges', payload);
|
||||
},
|
||||
removeFromDeleteRange({ commit }, payload) {
|
||||
commit('removeFromDeleteRange', payload);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default store;
|
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range
|
||||
* method GET, get Calendar ranges
|
||||
* @returns {Promise} a promise containing all Calendar ranges objects
|
||||
*/
|
||||
const fetchCalendarRanges = () => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
const fetchCalendarRangesByUser = (userId) => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json?user=${userId}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar
|
||||
* method GET, get Calendar events, can be filtered by mainUser
|
||||
* @returns {Promise} a promise containing all Calendar objects
|
||||
*/
|
||||
const fetchCalendar = (mainUserId) => {
|
||||
const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity_create
|
||||
* method POST, post CalendarRange entity
|
||||
*/
|
||||
const postCalendarRange = (body) => {
|
||||
const url = `/api/1.0/calendar/calendar-range.json?`;
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity
|
||||
* method PATCH, patch CalendarRange entity
|
||||
*/
|
||||
const patchCalendarRange = (id, body) => {
|
||||
console.log(body)
|
||||
const url = `/api/1.0/calendar/calendar-range/${id}.json`;
|
||||
return fetch(url, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity
|
||||
* method DELETE, delete CalendarRange entity
|
||||
*/
|
||||
const deleteCalendarRange = (id) => {
|
||||
const url = `/api/1.0/calendar/calendar-range/${id}.json`;
|
||||
return fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
fetchCalendarRanges,
|
||||
fetchCalendar,
|
||||
fetchCalendarRangesByUser,
|
||||
postCalendarRange,
|
||||
patchCalendarRange,
|
||||
deleteCalendarRange
|
||||
};
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="calendar__controls">
|
||||
<h2 class="chill-red">{{ $t('choose_your_calendar_user') }}</h2>
|
||||
<VueMultiselect
|
||||
name="field"
|
||||
@@ -23,15 +23,10 @@
|
||||
<input type="checkbox" id="myCalendar" class="form-check-input" v-model="showMyCalendarWidget" />
|
||||
<label class="form-check-label" for="myCalendar">{{ $t('show_my_calendar') }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="weekends" class="form-check-input" @click="toggleWeekends" />
|
||||
<label class="form-check-label" for="weekends">{{ $t('show_weekends') }}</label>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { fetchCalendarRanges, fetchCalendar } from '../../_api/api'
|
||||
import { fetchCalendarRanges, fetchCalendar } from './js/api'
|
||||
import VueMultiselect from 'vue-multiselect';
|
||||
import { whoami } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api';
|
||||
|
||||
@@ -53,7 +48,7 @@ const COLORS = [ /* from https://colorbrewer2.org/#type=qualitative&scheme=Set3&
|
||||
export default {
|
||||
name: 'CalendarUserSelector',
|
||||
components: { VueMultiselect },
|
||||
props: ['users', 'updateEventsSource', 'calendarEvents', 'showMyCalendar', 'toggleMyCalendar', 'toggleWeekends'],
|
||||
props: ['users', 'updateEventsSource', 'calendarEvents', 'showMyCalendar', 'toggleMyCalendar'],
|
||||
data() {
|
||||
return {
|
||||
errorMsg: [],
|
||||
@@ -100,8 +95,7 @@ export default {
|
||||
({
|
||||
start: i.startDate.datetime,
|
||||
end: i.endDate.datetime,
|
||||
calendarRangeId: i.id,
|
||||
sourceColor: u.color
|
||||
calendarRangeId: i.id
|
||||
//display: 'background' // can be an option for the disponibility
|
||||
})
|
||||
);
|
||||
@@ -109,13 +103,15 @@ export default {
|
||||
events: arr,
|
||||
color: u.color,
|
||||
textColor: '#444444',
|
||||
editable: false,
|
||||
id: u.id
|
||||
})
|
||||
})
|
||||
|
||||
this.users.loaded = users;
|
||||
this.options = users;
|
||||
|
||||
console.log(users)
|
||||
console.log(calendarEvents)
|
||||
|
||||
this.calendarEvents.loaded = calendarEvents;
|
||||
whoami().then(me => new Promise((resolve, reject) => {
|
||||
@@ -134,8 +130,7 @@ export default {
|
||||
let calendarEventsCurrentUser = {
|
||||
events: events,
|
||||
color: 'darkblue',
|
||||
id: 1000,
|
||||
editable: false
|
||||
id: 1000
|
||||
};
|
||||
this.calendarEvents.user = calendarEventsCurrentUser;
|
||||
|
||||
@@ -201,3 +196,12 @@ export default {
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.calendar__controls {
|
||||
background-color: 'black';
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range
|
||||
* method GET, get Calendar ranges
|
||||
* @returns {Promise} a promise containing all Calendar ranges objects
|
||||
*/
|
||||
const fetchCalendarRanges = () => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar
|
||||
* method GET, get Calendar events, can be filtered by mainUser
|
||||
* @returns {Promise} a promise containing all Calendar objects
|
||||
*/
|
||||
const fetchCalendar = (mainUserId) => {
|
||||
const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
fetchCalendarRanges,
|
||||
fetchCalendar
|
||||
};
|
@@ -2,8 +2,7 @@ const calendarUserSelectorMessages = {
|
||||
fr: {
|
||||
choose_your_calendar_user: "Afficher les plages de disponibilités",
|
||||
select_user: "Sélectionnez des calendriers",
|
||||
show_my_calendar: "Afficher mon calendrier",
|
||||
show_weekends: "Afficher les week-ends"
|
||||
show_my_calendar: "Afficher mon calendrier"
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
{% set activeRouteKey = 'chill_calendar_calendar' %}
|
||||
|
||||
{% block title 'Remove calendar item'|trans %}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
{
|
||||
'title' : 'Remove calendar item'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the calendar item?'|trans,
|
||||
'cancel_route' : 'chill_calendar_calendar_list',
|
||||
'cancel_parameters' : { 'accompanying_period_id' : accompanyingCourse.id, 'id' : calendar.id },
|
||||
'cancel_route' : 'chill_calendar_calendar',
|
||||
'cancel_parameters' : { 'accompanying_course_id' : accompanyingCourse.id, 'id' : calendar.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@@ -1,18 +0,0 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% set user = calendar.user %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title 'Remove activity'|trans %}
|
||||
|
||||
{% block content %}
|
||||
{{ include('@ChillMain/Util/confirmation_template.html.twig',
|
||||
{
|
||||
'title' : 'Remove calendar item'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the calendar item?'|trans,
|
||||
'cancel_route' : 'chill_calendar_calendar_list',
|
||||
'cancel_parameters' : { 'user_id' : calendar.user.id, 'id' : calendar.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@@ -0,0 +1,17 @@
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
{% set person = activity.person %}
|
||||
|
||||
{% block title 'Remove activity'|trans %}
|
||||
|
||||
{% block personcontent %}
|
||||
{{ include('@ChillMain/Util/confirmation_template.html.twig',
|
||||
{
|
||||
'title' : 'Remove activity'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the activity about "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname } ),
|
||||
'cancel_route' : 'chill_activity_activity_list',
|
||||
'cancel_parameters' : { 'person_id' : activity.person.id, 'id' : activity.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@@ -48,20 +48,16 @@
|
||||
{{ form_row(form.sendSMS) }}
|
||||
{% endif %}
|
||||
|
||||
{% if context == 'user' %}
|
||||
<div id="calendarControls"></div>
|
||||
{% endif %}
|
||||
|
||||
<div id="fullCalendar"></div>
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a
|
||||
class="btn btn-cancel"
|
||||
{%- if context == 'user' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'user_id': user.id } )}}"
|
||||
{%- elseif context == 'accompanyingCourse' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
{%- if context == 'person' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'person_id': person.id } )}}"
|
||||
{%- else -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
{%- endif -%}
|
||||
>
|
||||
{{ 'Cancel'|trans|chill_return_path_label }}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title 'Update calendar'|trans %}
|
||||
{% block title 'Update calendar'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="calendar-edit">
|
||||
@@ -35,7 +35,6 @@
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{{ encore_entry_link_tags('page_calendar') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block block_post_menu %}
|
@@ -1,36 +0,0 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title 'Update calendar'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="calendar-edit">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10 col-xxl">
|
||||
|
||||
<div id="calendar"></div> {# <=== vue component #}
|
||||
{% include 'ChillCalendarBundle:Calendar:edit.html.twig' with {'context': 'user'} %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
|
||||
});
|
||||
window.entity = {{ entity_json|json_encode|raw }};
|
||||
window.startDate = {{ entity.startDate|date('Y-m-d H:i:s')|json_encode|raw }};
|
||||
window.endDate = {{ entity.endDate|date('Y-m-d H:i:s')|json_encode|raw }};
|
||||
window.mainUser = {{ entity.mainUser.id }};
|
||||
</script>
|
||||
{{ encore_entry_script_tags('vue_calendar') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{% endblock %}
|
@@ -0,0 +1,145 @@
|
||||
{% set user_id = null %}
|
||||
{% if user %}
|
||||
{% set user_id = user.id %}
|
||||
{% endif %}
|
||||
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ 'Calendar list' |trans }}</h2>
|
||||
|
||||
{% if calendarItems|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There is no calendar items."|trans }}
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table list-records context-{{ context }}">
|
||||
|
||||
{% for calendar in calendarItems %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
|
||||
{% if calendar.startDate and calendar.endDate %}
|
||||
{% if calendar.endDate.diff(calendar.startDate).days >= 1 %}
|
||||
<h3>{{ "From the day"|trans }} {{ calendar.startDate|format_datetime('medium', 'short') }} </h3>
|
||||
<h3>{{ "to the day"|trans }} {{ calendar.endDate|format_datetime('medium', 'short') }}</h3>
|
||||
{% else %}
|
||||
<h3>{{ calendar.startDate|format_date('full') }} </h3>
|
||||
<h3>{{ calendar.startDate|format_datetime('none', 'short', locale='fr') }} - {{ calendar.endDate|format_datetime('none', 'short', locale='fr') }}</h3>
|
||||
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if context == 'user' and calendar.accompanyingPeriod is not empty %}
|
||||
<div class="accompanyingPeriodLink" style="margin-top: 1rem">
|
||||
<a
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_user_accompanying_course_index",
|
||||
{ 'accompanying_period_id': calendar.accompanyingPeriod.id }
|
||||
) }}"
|
||||
>
|
||||
<i class="fa fa-random"></i>
|
||||
{{ calendar.accompanyingPeriod.id }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if calendar.user %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ calendar.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if calendar.mainUser is not empty %}
|
||||
<li>
|
||||
<b>{{ 'main user concerned'|trans }}: {{ calendar.mainUser.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<li>
|
||||
{%- if calendar.comment.isEmpty -%}
|
||||
<span class="chill-no-data-statement">{{ 'No comments'|trans }}</span>
|
||||
{%- else -%}
|
||||
{{ calendar.comment|chill_entity_render_box }}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_show', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_edit', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': calendar.id, 'user_id' : user_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{%
|
||||
if calendar.comment.comment is not empty
|
||||
or calendar.users|length > 0
|
||||
or calendar.thirdParties|length > 0
|
||||
or calendar.users|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': calendar } %}
|
||||
</div>
|
||||
|
||||
{% if calendar.comment.comment is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if context != 'user' %}
|
||||
{# TODO set this condition in configuration #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new calendar' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
@@ -4,123 +4,6 @@
|
||||
|
||||
{% block title %}{{ 'Calendar list' |trans }}{% endblock title %}
|
||||
|
||||
{% set user_id = null %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ 'Calendar list' |trans }}</h1>
|
||||
|
||||
{% if calendarItems|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There is no calendar items."|trans }}
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table list-records context-accompanyingCourse">
|
||||
|
||||
{% for calendar in calendarItems %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
{% if calendar.startDate and calendar.endDate %}
|
||||
{% if calendar.endDate.diff(calendar.startDate).days >= 1 %}
|
||||
<h3>{{ "From the day"|trans }} {{ calendar.startDate|format_datetime('medium', 'short') }} </h3>
|
||||
<h3>{{ "to the day"|trans }} {{ calendar.endDate|format_datetime('medium', 'short') }}</h3>
|
||||
{% else %}
|
||||
<h3>{{ calendar.startDate|format_date('full') }} </h3>
|
||||
<h3>{{ calendar.startDate|format_datetime('none', 'short', locale='fr') }} - {{ calendar.endDate|format_datetime('none', 'short', locale='fr') }}</h3>
|
||||
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if calendar.user %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ calendar.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if calendar.mainUser is not empty %}
|
||||
<li>
|
||||
<b>{{ 'main user concerned'|trans }}: {{ calendar.mainUser.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_show', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_edit', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': calendar.id, 'user_id' : user_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{%
|
||||
if calendar.comment.comment is not empty
|
||||
or calendar.users|length > 0
|
||||
or calendar.thirdParties|length > 0
|
||||
or calendar.users|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': accompanyingCourse, 'with_display': 'row', 'entity': calendar } %}
|
||||
</div>
|
||||
|
||||
{% if calendar.comment.comment is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if calendarItems|length < paginator.getTotalItems %}
|
||||
{{ chill_pagination(paginator) }}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new calendar' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
{% include 'ChillCalendarBundle:Calendar:list.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
{% endblock %}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title %}{{ 'My calendar list' |trans }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ 'My calendar list' |trans }}</h1>
|
||||
<div id="myCalendar"></div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
window.userId = {{ user.id }};
|
||||
</script>
|
||||
{{ encore_entry_script_tags('vue_mycalendarrange') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{{ encore_entry_link_tags('page_calendar') }}
|
||||
{% endblock %}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user