mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 03:08:25 +00:00 
			
		
		
		
	Merge branch 'master' into person_renderbox_thirdparty_onthefly
This commit is contained in:
		@@ -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,6 +31,9 @@
 | 
			
		||||
         <!-- 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>
 | 
			
		||||
    </testsuites>
 | 
			
		||||
 | 
			
		||||
    <listeners>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Controller;
 | 
			
		||||
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Controller for activity configuration
 | 
			
		||||
 *
 | 
			
		||||
 * @author Julien Fastré <julien.fastre@champs-libres.coop>
 | 
			
		||||
 * @author Champs Libres <info@champs-libres.coop>
 | 
			
		||||
 */
 | 
			
		||||
class AdminController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    public function redirectToAdminIndexAction()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->redirectToRoute('chill_main_admin_central');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Controller;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class AsideActivityBundle
 | 
			
		||||
 */
 | 
			
		||||
class AsideActivityController extends CRUDController
 | 
			
		||||
final class AsideActivityController extends CRUDController
 | 
			
		||||
{
 | 
			
		||||
  
 | 
			
		||||
    protected function buildQueryEntities(string $action, Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $qb = parent::buildQueryEntities($action, $request);
 | 
			
		||||
 | 
			
		||||
        if ('index' === $action) {
 | 
			
		||||
            $qb->andWhere($qb->expr()->eq('e.agent', ':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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
<?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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
<?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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,8 +25,9 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
 | 
			
		||||
    public function load(array $configs, ContainerBuilder $container): void
 | 
			
		||||
    {
 | 
			
		||||
        $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)
 | 
			
		||||
 
 | 
			
		||||
@@ -200,10 +200,4 @@ class AsideActivity implements TrackUpdateInterface, TrackCreationInterface
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // public function __toString()
 | 
			
		||||
    // {
 | 
			
		||||
    //     // dump($this->type->getTitle());
 | 
			
		||||
    //     return $this->type->getTitle();
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,9 @@ 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 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;
 | 
			
		||||
@@ -26,8 +28,12 @@ final class AsideActivityFormType extends AbstractType
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
    private TokenStorageInterface $storage;
 | 
			
		||||
 | 
			
		||||
    public function __construct (TranslatableStringHelper $translatableStringHelper, array $timeChoices, TokenStorageInterface $storage){
 | 
			
		||||
        $this->timeChoices = $timeChoices;
 | 
			
		||||
    public function __construct (
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        ParameterBagInterface $parameterBag,
 | 
			
		||||
        TokenStorageInterface $storage
 | 
			
		||||
    ){
 | 
			
		||||
        $this->timeChoices = $parameterBag->get('chill_activity.form.time_duration');
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->storage = $storage;
 | 
			
		||||
    }
 | 
			
		||||
@@ -47,12 +53,15 @@ 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 '),
 | 
			
		||||
                'placeholder' => 'Choose the agent for whom this activity is created',
 | 
			
		||||
                'choice_label' => 'username'
 | 
			
		||||
@@ -85,7 +94,7 @@ final class AsideActivityFormType extends AbstractType
 | 
			
		||||
                'required' => false,
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            foreach (['duration'] as $fieldName) 
 | 
			
		||||
            foreach (['duration'] as $fieldName)
 | 
			
		||||
            {
 | 
			
		||||
                $builder->get($fieldName)
 | 
			
		||||
                ->addModelTransformer($durationTimeTransformer);
 | 
			
		||||
@@ -108,7 +117,6 @@ 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
 | 
			
		||||
@@ -131,7 +139,7 @@ final class AsideActivityFormType extends AbstractType
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver): void
 | 
			
		||||
    {
 | 
			
		||||
        $resolver->setDefaults([
 | 
			
		||||
            'data_class' => AsideActivity::class, 
 | 
			
		||||
            'data_class' => AsideActivity::class,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -139,4 +147,4 @@ final class AsideActivityFormType extends AbstractType
 | 
			
		||||
    {
 | 
			
		||||
        return 'chill_asideactivitybundle_asideactivity';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Menu;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
 | 
			
		||||
use Knp\Menu\MenuItem;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class SectionMenuBuilder
 | 
			
		||||
 *
 | 
			
		||||
 * @package Chill\AsideActivityBundle\Menu
 | 
			
		||||
 */
 | 
			
		||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
{
 | 
			
		||||
    protected TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param $menuId
 | 
			
		||||
     * @param MenuItem $menu
 | 
			
		||||
     * @param array $parameters
 | 
			
		||||
     */
 | 
			
		||||
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
 | 
			
		||||
    {
 | 
			
		||||
        $menu->addChild($this->translator->trans('Create an aside activity'), [
 | 
			
		||||
                'route' => 'chill_crud_aside_activity_new'
 | 
			
		||||
            ])
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => 11,
 | 
			
		||||
                'icons' => [ 'plus' ]
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public static function getMenuIds(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [ 'section' ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% block vertical_menu_content %}
 | 
			
		||||
	{{ chill_menu('admin_aside_activity', {
 | 
			
		||||
        'layout': '@ChillAsideActivity/Admin/menu_asideactivity.html.twig',
 | 
			
		||||
    }) }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block layout_wvm_content %}
 | 
			
		||||
	{% block admin_content %}
 | 
			
		||||
		<!-- block personcontent empty -->
 | 
			
		||||
		<h1>{{ 'Aside activity configuration' |trans }}</h1>
 | 
			
		||||
	{% endblock %}
 | 
			
		||||
{% endblock  %}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
{% extends "@ChillMain/Menu/verticalMenu.html.twig" %}
 | 
			
		||||
{% block v_menu_title %}
 | 
			
		||||
	{{ 'Aside activity configuration menu'|trans }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -1,37 +1,30 @@
 | 
			
		||||
<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 %}{% 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>
 | 
			
		||||
	<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 %}
 | 
			
		||||
 | 
			
		||||
    {{ form_end(form) }}
 | 
			
		||||
</div>
 | 
			
		||||
        {% 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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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,5 +9,6 @@
 | 
			
		||||
{% 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,107 +1,97 @@
 | 
			
		||||
{% extends "@ChillMain/layout.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{{ 'Aside activity list' |trans }}{% endblock title %}
 | 
			
		||||
{% block title %}
 | 
			
		||||
	{{ 'Aside activity list' |trans }}
 | 
			
		||||
{% endblock title %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="col-md-10 col-xxl asideactivity-list">
 | 
			
		||||
<h2>{{ 'My aside activities' |trans }}</h2>
 | 
			
		||||
	<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 aren't any aside activities."|trans }}
 | 
			
		||||
        <a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
 | 
			
		||||
    </p>
 | 
			
		||||
{% else %}
 | 
			
		||||
		{% 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 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 %}
 | 
			
		||||
			<div
 | 
			
		||||
				class="flex-table my-4 list-records">
 | 
			
		||||
				{# Sort activities according to date in descending order #}
 | 
			
		||||
				{% for entity in entities %}
 | 
			
		||||
					{% 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">
 | 
			
		||||
 | 
			
		||||
        <div class="item-bloc">
 | 
			
		||||
            <div class="item-row main">
 | 
			
		||||
                <div class="item-col">
 | 
			
		||||
								<h3>
 | 
			
		||||
									<b>{{ entity.type.title | localize_translatable_string }}</b>
 | 
			
		||||
								</h3>
 | 
			
		||||
 | 
			
		||||
                    <h3>
 | 
			
		||||
                        <b>{{ entity.type.title | localize_translatable_string }}</b>
 | 
			
		||||
                    </h3>
 | 
			
		||||
								{% if entity.date %}
 | 
			
		||||
									<p>{{ entity.date|format_date('long') }}</p>
 | 
			
		||||
								{% endif %}
 | 
			
		||||
 | 
			
		||||
                    {% 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 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>
 | 
			
		||||
 | 
			
		||||
                </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 %}
 | 
			
		||||
 | 
			
		||||
            {# {%
 | 
			
		||||
                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="{{ 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>
 | 
			
		||||
							</ul>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
            </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>
 | 
			
		||||
    <ul class="record_actions">
 | 
			
		||||
        <li>
 | 
			
		||||
            <a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create">
 | 
			
		||||
                {{ 'Add a new aside activity' | trans }}
 | 
			
		||||
            </a>
 | 
			
		||||
        </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
				{% 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>
 | 
			
		||||
		</div>
 | 
			
		||||
	{% endif %}
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,44 +1,44 @@
 | 
			
		||||
{% extends "@ChillActivity/Admin/layout_activity.html.twig" %}
 | 
			
		||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
    <h1>{{ 'ActivityType list'|trans }}</h1>
 | 
			
		||||
	<h1>{{ 'ActivityType list'|trans }}</h1>
 | 
			
		||||
 | 
			
		||||
    <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>
 | 
			
		||||
	<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">
 | 
			
		||||
							<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_aside_activity_category_new') }}" class="btn btn-create">
 | 
			
		||||
				{{ 'Create a new aside activity type'|trans }}
 | 
			
		||||
			</a>
 | 
			
		||||
		</li>
 | 
			
		||||
	</ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,73 @@
 | 
			
		||||
<?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,3 +1,12 @@
 | 
			
		||||
chill_asideactivities_controllers:
 | 
			
		||||
    resource: "@ChillAsideActivityBundle/Controller"
 | 
			
		||||
    type: annotation
 | 
			
		||||
  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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,5 @@
 | 
			
		||||
# 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 }
 | 
			
		||||
services:
 | 
			
		||||
    Chill\AsideActivityBundle\DataFixtures\:
 | 
			
		||||
        resource: './../DataFixtures'
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,6 @@
 | 
			
		||||
---
 | 
			
		||||
services:
 | 
			
		||||
    chill.asideactivity.form.type.asideactivity:
 | 
			
		||||
        class: Chill\AsideActivityBundle\Form\AsideActivityFormType
 | 
			
		||||
        arguments:
 | 
			
		||||
            - "@chill.main.helper.translatable_string"
 | 
			
		||||
            - "%chill_activity.form.time_duration%"
 | 
			
		||||
            - "@security.token_storage"
 | 
			
		||||
        tags:
 | 
			
		||||
            - { name: form.type, alias: chill_asideactivitybundle_asideactivity }
 | 
			
		||||
    Chill\AsideActivityBundle\Form\:
 | 
			
		||||
        resource: './../../Form'
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
services:
 | 
			
		||||
  Chill\AsideActivityBundle\Menu\:
 | 
			
		||||
    resource: './../../Menu'
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
#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
 | 
			
		||||
@@ -25,7 +26,7 @@ Required: Obligatoire
 | 
			
		||||
Persons: Personnes
 | 
			
		||||
Users: Utilisateurs
 | 
			
		||||
Emergency: Urgent
 | 
			
		||||
by: 'Par '
 | 
			
		||||
by: "Par "
 | 
			
		||||
location: Lieu
 | 
			
		||||
 | 
			
		||||
# Crud
 | 
			
		||||
@@ -33,10 +34,10 @@ crud:
 | 
			
		||||
  aside_activity:
 | 
			
		||||
    title_view: Détail de l'activité annexe
 | 
			
		||||
    title_new: Nouvelle activité annexe
 | 
			
		||||
    title_edit: Edition d'une activité annexe
 | 
			
		||||
    title_delete: Supprimation d'une activité annexe
 | 
			
		||||
    title_edit: Édition d'une activité annexe
 | 
			
		||||
    title_delete: Supprimer une activité annexe
 | 
			
		||||
    button_delete: Supprimer
 | 
			
		||||
    confirm_message_delete: Êtes-vous sûr de vouloir supprimer cet activité annexe?
 | 
			
		||||
    confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
 | 
			
		||||
  aside_activity_category:
 | 
			
		||||
    title_new: Nouvelle catégorie d'activité annexe
 | 
			
		||||
    title_edit: Edition d'une catégorie de type d'activité
 | 
			
		||||
@@ -57,26 +58,18 @@ Agent: Utilisateur
 | 
			
		||||
date: Date
 | 
			
		||||
Duration: Durée
 | 
			
		||||
Note: Note
 | 
			
		||||
5 minutes: 5 minutes
 | 
			
		||||
10 minutes: 10 minutes
 | 
			
		||||
15 minutes: 15 minutes
 | 
			
		||||
20 minutes: 20 minutes
 | 
			
		||||
25 minutes: 25 minutes
 | 
			
		||||
30 minutes: 30 minutes
 | 
			
		||||
45 minutes: 45 minutes
 | 
			
		||||
1 hour: 1 heure
 | 
			
		||||
1 hour 15: 1 heure 15
 | 
			
		||||
1 hour 30: 1 heure 30
 | 
			
		||||
1 hour 45: 1 heure 45
 | 
			
		||||
2 hours: 2 heures
 | 
			
		||||
 | 
			
		||||
#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: "Creér une activité annexe"
 | 
			
		||||
Aside activity configuration menu: "Menu de configuration des activités annexes"
 | 
			
		||||
Aside activity configuration: "Configuration des activités annexes"
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Lists all Calendar entities.
 | 
			
		||||
     * @Route("/{_locale}/calendar/", name="chill_calendar_calendar")
 | 
			
		||||
     * @Route("/{_locale}/calendar/calendar/", name="chill_calendar_calendar_list")
 | 
			
		||||
     */
 | 
			
		||||
    public function listAction(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -80,18 +80,17 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        if ($user instanceof User) {
 | 
			
		||||
 | 
			
		||||
            // $calendar = $em->getRepository(Calendar::class)
 | 
			
		||||
            //     ->findByUser($user)
 | 
			
		||||
            //     ;
 | 
			
		||||
 | 
			
		||||
            // $view = 'ChillCalendarBundle:Calendar:listByUser.html.twig';
 | 
			
		||||
            $calendarItems = $em->getRepository(Calendar::class)
 | 
			
		||||
                ->findByUser($user)
 | 
			
		||||
                ;
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/listByUser.html.twig';
 | 
			
		||||
        } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $calendarItems = $em->getRepository(Calendar::class)->findBy(
 | 
			
		||||
                ['accompanyingPeriod' => $accompanyingPeriod],
 | 
			
		||||
                ['startDate' => 'DESC']
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            $view = 'ChillCalendarBundle:Calendar:listByAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/listByAccompanyingCourse.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render($view, [
 | 
			
		||||
@@ -103,7 +102,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new calendar item
 | 
			
		||||
     * @Route("/{_locale}/calendar/new", name="chill_calendar_calendar_new")
 | 
			
		||||
     * @Route("/{_locale}/calendar/calendar/new", name="chill_calendar_calendar_new")
 | 
			
		||||
     */
 | 
			
		||||
    public function newAction(Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -112,10 +111,10 @@ class CalendarController extends AbstractController
 | 
			
		||||
        [$user, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillCalendarBundle:Calendar:newAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/newAccompanyingCourse.html.twig';
 | 
			
		||||
        } 
 | 
			
		||||
        // elseif ($user instanceof User) {
 | 
			
		||||
        //     $view = 'ChillCalendarBundle:Calendar:newUser.html.twig';
 | 
			
		||||
        //     $view = '@ChillCalendar/Calendar/newUser.html.twig';
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        $entity = new Calendar();
 | 
			
		||||
@@ -142,7 +141,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
            $params = $this->buildParamsToUrl($user, $accompanyingPeriod);
 | 
			
		||||
 | 
			
		||||
            return $this->redirectToRoute('chill_calendar_calendar', $params);
 | 
			
		||||
            return $this->redirectToRoute('chill_calendar_calendar_list', $params);
 | 
			
		||||
        } elseif ($form->isSubmitted() and !$form->isValid()) {
 | 
			
		||||
            $this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
 | 
			
		||||
        }
 | 
			
		||||
@@ -165,7 +164,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Show a calendar item
 | 
			
		||||
     * @Route("/{_locale}/calendar/{id}/show", name="chill_calendar_calendar_show")
 | 
			
		||||
     * @Route("/{_locale}/calendar/calendar/{id}/show", name="chill_calendar_calendar_show")
 | 
			
		||||
     */
 | 
			
		||||
    public function showAction(Request $request, $id): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -174,11 +173,11 @@ class CalendarController extends AbstractController
 | 
			
		||||
        [$user, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/showByAccompanyingCourse.html.twig';
 | 
			
		||||
        } 
 | 
			
		||||
        // elseif ($person instanceof Person) {
 | 
			
		||||
        //     $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig';
 | 
			
		||||
        // }
 | 
			
		||||
        elseif ($user instanceof User) {
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/showByUser.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
 | 
			
		||||
 | 
			
		||||
@@ -198,9 +197,9 @@ class CalendarController extends AbstractController
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->render($view, [
 | 
			
		||||
            //'person'      => $person,
 | 
			
		||||
            'accompanyingCourse' => $accompanyingPeriod,
 | 
			
		||||
            'entity'      => $entity,
 | 
			
		||||
            'user' => $user
 | 
			
		||||
            //'delete_form' => $deleteForm->createView(),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -209,7 +208,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
 | 
			
		||||
     /**
 | 
			
		||||
     * Edit a calendar item
 | 
			
		||||
     * @Route("/{_locale}/calendar/{id}/edit", name="chill_calendar_calendar_edit")
 | 
			
		||||
     * @Route("/{_locale}/calendar/calendar/{id}/edit", name="chill_calendar_calendar_edit")
 | 
			
		||||
     */
 | 
			
		||||
    public function editAction($id, Request $request): Response
 | 
			
		||||
    {
 | 
			
		||||
@@ -218,11 +217,11 @@ class CalendarController extends AbstractController
 | 
			
		||||
        [$user, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/editByAccompanyingCourse.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
         elseif ($user instanceof User) {
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/editByUser.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
        //  elseif ($person instanceof Person) {
 | 
			
		||||
        //     $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig';
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
 | 
			
		||||
 | 
			
		||||
@@ -241,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', $params);
 | 
			
		||||
            return $this->redirectToRoute('chill_calendar_calendar_list', $params);
 | 
			
		||||
        } elseif ($form->isSubmitted() and !$form->isValid()) {
 | 
			
		||||
            $this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
 | 
			
		||||
        }
 | 
			
		||||
@@ -259,6 +258,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
            'form' => $form->createView(),
 | 
			
		||||
            'delete_form' => $deleteForm->createView(),
 | 
			
		||||
            'accompanyingCourse' => $accompanyingPeriod,
 | 
			
		||||
            'user' => $user,
 | 
			
		||||
            'entity_json' => $entity_array
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -274,11 +274,11 @@ class CalendarController extends AbstractController
 | 
			
		||||
        [$user, $accompanyingPeriod] = $this->getEntity($request);
 | 
			
		||||
 | 
			
		||||
        if ($accompanyingPeriod instanceof AccompanyingPeriod) {
 | 
			
		||||
            $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig';
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/confirm_deleteByAccompanyingCourse.html.twig';
 | 
			
		||||
        } 
 | 
			
		||||
        // elseif ($person instanceof Person) {
 | 
			
		||||
        //     $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig';
 | 
			
		||||
        // }
 | 
			
		||||
        elseif ($user instanceof User) {
 | 
			
		||||
            $view = '@ChillCalendar/Calendar/confirm_deleteByUser.html.twig';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* @var $entity Calendar */
 | 
			
		||||
        $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
 | 
			
		||||
@@ -306,7 +306,7 @@ class CalendarController extends AbstractController
 | 
			
		||||
                      ->trans("The calendar item has been successfully removed."));
 | 
			
		||||
 | 
			
		||||
                $params = $this->buildParamsToUrl($user, $accompanyingPeriod);
 | 
			
		||||
                return $this->redirectToRoute('chill_calendar_calendar', $params);
 | 
			
		||||
                return $this->redirectToRoute('chill_calendar_calendar_list', $params);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -324,9 +324,9 @@ class CalendarController extends AbstractController
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a form to delete a Calendar entity by id.
 | 
			
		||||
     */
 | 
			
		||||
    private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form
 | 
			
		||||
    private function createDeleteForm(int $id, ?User $user, ?AccompanyingPeriod $accompanyingPeriod): Form
 | 
			
		||||
    {
 | 
			
		||||
        $params = $this->buildParamsToUrl($person, $accompanyingPeriod);
 | 
			
		||||
        $params = $this->buildParamsToUrl($user, $accompanyingPeriod);
 | 
			
		||||
        $params['id'] = $id;
 | 
			
		||||
 | 
			
		||||
        return $this->createFormBuilder()
 | 
			
		||||
@@ -350,7 +350,8 @@ class CalendarController extends AbstractController
 | 
			
		||||
                throw $this->createNotFoundException('User not found');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user);
 | 
			
		||||
            // TODO Add permission
 | 
			
		||||
            // $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,16 +18,19 @@ class CalendarRangeAPIController extends ApiController
 | 
			
		||||
     */
 | 
			
		||||
    public function availableRanges(Request $request, string $_format): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        if ($request->query->has('user')) {
 | 
			
		||||
            $user = $request->query->get('user');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $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)')
 | 
			
		||||
        ;
 | 
			
		||||
        $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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $results = $query->getResult();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -66,13 +66,16 @@ 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_HEAD => true,
 | 
			
		||||
                                Request::METHOD_POST => true,
 | 
			
		||||
                                Request::METHOD_PATCH => true,
 | 
			
		||||
                                Request::METHOD_DELETE => true,
 | 
			
		||||
                            ]
 | 
			
		||||
                        ],
 | 
			
		||||
                    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -37,14 +37,16 @@ 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;
 | 
			
		||||
    private ?User $user = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
 | 
			
		||||
@@ -64,6 +66,7 @@ class Calendar
 | 
			
		||||
     *     cascade={"persist", "remove", "merge", "detach"})
 | 
			
		||||
     * @ORM\JoinTable(name="chill_calendar.calendar_to_persons")
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     * @Serializer\Groups({"calendar:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $persons;
 | 
			
		||||
 | 
			
		||||
@@ -74,6 +77,7 @@ class Calendar
 | 
			
		||||
     *     cascade={"persist", "remove", "merge", "detach"})
 | 
			
		||||
     * @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties")
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     * @Serializer\Groups({"calendar:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private Collection $professionals;
 | 
			
		||||
 | 
			
		||||
@@ -89,6 +93,7 @@ class Calendar
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_")
 | 
			
		||||
     * @Serializer\Groups({"calendar:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private CommentEmbeddable $comment;
 | 
			
		||||
 | 
			
		||||
@@ -96,20 +101,20 @@ class Calendar
 | 
			
		||||
     * @ORM\Column(type="datetimetz_immutable")
 | 
			
		||||
     * @Serializer\Groups({"calendar:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private \DateTimeImmutable $startDate;
 | 
			
		||||
    private ?\DateTimeImmutable $startDate = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="datetimetz_immutable")
 | 
			
		||||
     * @Serializer\Groups({"calendar:read"})
 | 
			
		||||
     */
 | 
			
		||||
    private \DateTimeImmutable $endDate;
 | 
			
		||||
    private ?\DateTimeImmutable $endDate = null;
 | 
			
		||||
 | 
			
		||||
    //TODO Lieu
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="string", length=255)
 | 
			
		||||
     */
 | 
			
		||||
    private string $status;
 | 
			
		||||
    private ?string $status = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="CancelReason")
 | 
			
		||||
@@ -124,7 +129,7 @@ class Calendar
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\Activity")
 | 
			
		||||
     */
 | 
			
		||||
    private Activity $activity;
 | 
			
		||||
    private ?Activity $activity = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="boolean", nullable=true)
 | 
			
		||||
 
 | 
			
		||||
@@ -25,21 +25,21 @@ class CalendarRange
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
 | 
			
		||||
     * @Groups({"read"})
 | 
			
		||||
     * @groups({"read", "write"})
 | 
			
		||||
     */
 | 
			
		||||
    private User $user;
 | 
			
		||||
    private ?User $user = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="datetimetz_immutable")
 | 
			
		||||
     * @groups({"read"})
 | 
			
		||||
     * @groups({"read", "write"})
 | 
			
		||||
     */
 | 
			
		||||
    private \DateTimeImmutable $startDate;
 | 
			
		||||
    private ?\DateTimeImmutable $startDate = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="datetimetz_immutable")
 | 
			
		||||
     * @groups({"read"})
 | 
			
		||||
     * @groups({"read", "write"})
 | 
			
		||||
     */
 | 
			
		||||
    private \DateTimeImmutable $endDate;
 | 
			
		||||
    private ?\DateTimeImmutable $endDate = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\OneToMany(targetEntity=Calendar::class,
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
 | 
			
		||||
        if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
 | 
			
		||||
            $menu->addChild($this->translator->trans('Calendar'), [
 | 
			
		||||
                'route' => 'chill_calendar_calendar',
 | 
			
		||||
                'route' => 'chill_calendar_calendar_list',
 | 
			
		||||
                'routeParameters' => [
 | 
			
		||||
                    'accompanying_period_id' => $period->getId(),
 | 
			
		||||
                ]])
 | 
			
		||||
 
 | 
			
		||||
@@ -7,4 +7,14 @@ div#calendarControls {
 | 
			
		||||
 | 
			
		||||
div#fullCalendar{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.calendarRangeItems {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    a {
 | 
			
		||||
        text-decoration: none;
 | 
			
		||||
        padding: 3px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,468 @@
 | 
			
		||||
<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>
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
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
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
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');
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
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;
 | 
			
		||||
@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
* 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 class="calendar__controls">
 | 
			
		||||
  <div>
 | 
			
		||||
     <h2 class="chill-red">{{ $t('choose_your_calendar_user') }}</h2>
 | 
			
		||||
    <VueMultiselect
 | 
			
		||||
        name="field"
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
import { fetchCalendarRanges, fetchCalendar } from './js/api'
 | 
			
		||||
import { fetchCalendarRanges, fetchCalendar } from '../../_api/api'
 | 
			
		||||
import VueMultiselect from 'vue-multiselect';
 | 
			
		||||
import { whoami } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api';
 | 
			
		||||
 | 
			
		||||
@@ -201,12 +201,3 @@ 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>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +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');
 | 
			
		||||
      });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* 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
 | 
			
		||||
};
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% set activeRouteKey = 'chill_calendar_calendar' %}
 | 
			
		||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
 | 
			
		||||
 | 
			
		||||
{% 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',
 | 
			
		||||
            'cancel_parameters' : { 'accompanying_course_id' : accompanyingCourse.id, 'id' : calendar.id },
 | 
			
		||||
            'cancel_route'      : 'chill_calendar_calendar_list',
 | 
			
		||||
            'cancel_parameters' : { 'accompanying_period_id' : accompanyingCourse.id, 'id' : calendar.id },
 | 
			
		||||
            'form'              : delete_form
 | 
			
		||||
        } ) }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
{% 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 %}
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
{% 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,16 +48,20 @@
 | 
			
		||||
    {{ 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 == '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 } )}}"
 | 
			
		||||
      {%- 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 } )}}"
 | 
			
		||||
      {%- 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,6 +35,7 @@
 | 
			
		||||
{% block css %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_link_tags('vue_calendar') }}
 | 
			
		||||
    {{ encore_entry_link_tags('page_calendar') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block block_post_menu %}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
{% 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 %}
 | 
			
		||||
@@ -8,134 +8,128 @@
 | 
			
		||||
    {% set accompanying_course_id = accompanyingCourse.id %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
<h2>{{ 'Calendar list' |trans }}</h2>
 | 
			
		||||
{% if context == 'user' %}
 | 
			
		||||
    <h2>{{ 'My calendar list' |trans }}</h2>
 | 
			
		||||
{% else %}
 | 
			
		||||
    <h2>{{ 'Calendar list' |trans }}</h2>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% 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>
 | 
			
		||||
{% if context == 'user' %}
 | 
			
		||||
    <div id="myCalendar"></div>
 | 
			
		||||
{% else %}
 | 
			
		||||
 | 
			
		||||
<div class="flex-table list-records context-{{ context }}">
 | 
			
		||||
    {% 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 %}
 | 
			
		||||
 | 
			
		||||
    {% for calendar in calendarItems %}
 | 
			
		||||
    <div class="flex-table list-records context-{{ context }}">
 | 
			
		||||
 | 
			
		||||
        <div class="item-bloc">
 | 
			
		||||
            <div class="item-row main">
 | 
			
		||||
                <div class="item-col">
 | 
			
		||||
        {% 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>
 | 
			
		||||
                        {% 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 %}
 | 
			
		||||
 | 
			
		||||
                            <div class="duration">
 | 
			
		||||
                                <p>
 | 
			
		||||
                                    <i class="fa fa-fw fa-hourglass-end"></i>
 | 
			
		||||
                                    {{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
 | 
			
		||||
                                </p>
 | 
			
		||||
                            </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 %}
 | 
			
		||||
 | 
			
		||||
                        </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 %}
 | 
			
		||||
 | 
			
		||||
                    {% if context == 'user' and calendar.accompanyingPeriod is not empty %}
 | 
			
		||||
                        <a class="btn btn-sm btn-outline-primary"
 | 
			
		||||
                            title="{{ 'Period number %number%'|trans({'%number%': calendar.accompanyingPeriod.id}) }}"
 | 
			
		||||
                            href="{{ chill_path_add_return_path(
 | 
			
		||||
                                "chill_user_accompanying_course_index",
 | 
			
		||||
                                { 'accompanying_period_id': calendar.accompanyingPeriod.id }
 | 
			
		||||
                            ) }}"><i class="fa fa-random"></i>
 | 
			
		||||
                        </a>
 | 
			
		||||
                    {% 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 %}
 | 
			
		||||
        {% 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 %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </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 %}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
{% extends "@ChillMain/layout.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{{ 'My calendar list' |trans }}{% endblock title %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    {% include 'ChillCalendarBundle:Calendar:list.html.twig' with {'context': 'user'} %}
 | 
			
		||||
{% 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 %}
 | 
			
		||||
@@ -51,9 +51,9 @@
 | 
			
		||||
    <a 
 | 
			
		||||
      class="btn btn-cancel"
 | 
			
		||||
      {%- if context == 'person' -%} 
 | 
			
		||||
      href="{{ chill_return_path_or('chill_calendar_calendar', { 'person_id': person.id } )}}"
 | 
			
		||||
      href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'person_id': person.id } )}}"
 | 
			
		||||
      {%- else -%}
 | 
			
		||||
      href="{{ chill_return_path_or('chill_calendar_calendar', { 'accompanying_period_id': accompanyingCourse.id } )}}"
 | 
			
		||||
      href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
 | 
			
		||||
      {%- endif -%}
 | 
			
		||||
      >
 | 
			
		||||
      {{ 'Cancel'|trans|chill_return_path_label }}
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
 | 
			
		||||
{% block css %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    <link rel="stylesheet" href="{{ asset('build/vue_calendar.css') }}"/>
 | 
			
		||||
    {{ encore_entry_link_tags('vue_calendar') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block block_post_menu %}
 | 
			
		||||
 
 | 
			
		||||
@@ -58,24 +58,37 @@
 | 
			
		||||
    {% set accompanying_course_id = accompanyingCourse.id %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% set user_id = null %}
 | 
			
		||||
{% if user %}
 | 
			
		||||
    {% set user_id = user.id %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
<ul class="record_actions sticky-form-buttons">
 | 
			
		||||
    <li class="cancel">
 | 
			
		||||
        <a class="btn btn-cancel" href="{{ path('chill_calendar_calendar', { 'accompanying_period_id': accompanying_course_id } ) }}">
 | 
			
		||||
        <a class="btn btn-cancel" href="{{ path('chill_calendar_calendar_list', { 'accompanying_period_id': accompanying_course_id, 'user_id': user_id } ) }}">
 | 
			
		||||
            {{ 'Back to the list'|trans }}
 | 
			
		||||
        </a>
 | 
			
		||||
    </li>
 | 
			
		||||
    {% if accompanyingCourse %}
 | 
			
		||||
    <li>
 | 
			
		||||
        <a class="btn btn-update" href="{{ path('chill_calendar_calendar_edit', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id }) }}">
 | 
			
		||||
            {{ 'Edit'|trans }}
 | 
			
		||||
        </a>
 | 
			
		||||
    </li>
 | 
			
		||||
    
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    {% if user %}
 | 
			
		||||
    <li>
 | 
			
		||||
        <a class="btn btn-update" href="{{ path('chill_calendar_calendar_edit', { 'id': entity.id, 'user_id': user_id }) }}">
 | 
			
		||||
            {{ 'Edit'|trans }}
 | 
			
		||||
        </a>
 | 
			
		||||
    </li>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    {# TODO
 | 
			
		||||
    {% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
 | 
			
		||||
    #}
 | 
			
		||||
    
 | 
			
		||||
    <li>
 | 
			
		||||
        <a href="{{ path('chill_calendar_calendar_delete', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete">
 | 
			
		||||
        <a href="{{ path('chill_calendar_calendar_delete', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id, 'user_id': user_id } ) }}" class="btn btn-delete">
 | 
			
		||||
            {{ 'Delete'|trans }}
 | 
			
		||||
        </a>
 | 
			
		||||
    </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,13 @@
 | 
			
		||||
{% extends "@ChillMain/layout.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% block title 'Calendar'|trans %}
 | 
			
		||||
 | 
			
		||||
{% block content -%}
 | 
			
		||||
<div class="calendar-show">
 | 
			
		||||
    <div class="row justify-content-center">
 | 
			
		||||
        <div class="col-md-10 col-xxl">           
 | 
			
		||||
            {% include 'ChillCalendarBundle:Calendar:show.html.twig' with {'context': 'user'} %}
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div> 
 | 
			
		||||
{% endblock content %}
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\CalendarBundle\Tests\Controller;
 | 
			
		||||
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
 | 
			
		||||
class CalendarControllerTest extends WebTestCase
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Setup before the first test of this class (see phpunit doc)
 | 
			
		||||
     */
 | 
			
		||||
    public static function setUpBeforeClass()
 | 
			
		||||
    {
 | 
			
		||||
        static::bootKernel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Setup before each test method (see phpunit doc)
 | 
			
		||||
     */
 | 
			
		||||
    public function setUp()
 | 
			
		||||
    {
 | 
			
		||||
        $this->client = static::createClient(array(), array(
 | 
			
		||||
           'PHP_AUTH_USER' => 'center a_social',
 | 
			
		||||
           'PHP_AUTH_PW'   => 'password',
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private function getAccompanyingPeriodFromFixtures(): AccompanyingPeriod
 | 
			
		||||
    {
 | 
			
		||||
        $em = static::$kernel->getContainer()
 | 
			
		||||
              ->get('doctrine.orm.entity_manager');
 | 
			
		||||
 | 
			
		||||
        $accompanying_period = $em->getRepository('ChillPersonBundle:AccompanyingPeriod')->find(1);
 | 
			
		||||
 | 
			
		||||
        if ($accompanying_period === NULL) {
 | 
			
		||||
            throw new \RuntimeException("We need an accompanying course with id = 1. Did you add fixtures ?");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $accompanying_period;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testList()
 | 
			
		||||
    {
 | 
			
		||||
        $this->client->request(
 | 
			
		||||
            Request::METHOD_GET, 
 | 
			
		||||
            sprintf('/fr/calendar/?accompanying_period_id=%d', $this->getAccompanyingPeriodFromFixtures()->getId())
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function testNew()
 | 
			
		||||
    {
 | 
			
		||||
        $this->client->request(
 | 
			
		||||
            Request::METHOD_GET, 
 | 
			
		||||
            sprintf('/fr/calendar/new?accompanying_period_id=%d', $this->getAccompanyingPeriodFromFixtures()->getId())
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -8,6 +8,28 @@ servers:
 | 
			
		||||
  - url: "/api"
 | 
			
		||||
    description: "Your current dev server"
 | 
			
		||||
 | 
			
		||||
components:
 | 
			
		||||
  schemas:
 | 
			
		||||
    Date:
 | 
			
		||||
      type: object
 | 
			
		||||
      properties:
 | 
			
		||||
        datetime:
 | 
			
		||||
          type: string
 | 
			
		||||
          format: date-time
 | 
			
		||||
    User:
 | 
			
		||||
      type: object
 | 
			
		||||
      properties:
 | 
			
		||||
        id:
 | 
			
		||||
          type: integer
 | 
			
		||||
        type:
 | 
			
		||||
          type: string
 | 
			
		||||
          enum:
 | 
			
		||||
            - user
 | 
			
		||||
        username:
 | 
			
		||||
          type: string
 | 
			
		||||
        text:
 | 
			
		||||
          type: string
 | 
			
		||||
 | 
			
		||||
paths:
 | 
			
		||||
  /1.0/calendar/calendar.json:
 | 
			
		||||
    get:
 | 
			
		||||
@@ -48,6 +70,34 @@ paths:
 | 
			
		||||
      responses:
 | 
			
		||||
        200:
 | 
			
		||||
          description: "ok"
 | 
			
		||||
    post:
 | 
			
		||||
      tags:
 | 
			
		||||
        - calendar
 | 
			
		||||
      summary: create a new calendar range
 | 
			
		||||
      requestBody:
 | 
			
		||||
        required: true
 | 
			
		||||
        content:
 | 
			
		||||
          application/json:
 | 
			
		||||
            schema:
 | 
			
		||||
              type: object
 | 
			
		||||
              properties:
 | 
			
		||||
                user:
 | 
			
		||||
                  $ref: '#/components/schemas/User'
 | 
			
		||||
                startDate:
 | 
			
		||||
                  $ref: '#/components/schemas/Date'
 | 
			
		||||
                endDate:
 | 
			
		||||
                  $ref: '#/components/schemas/Date'
 | 
			
		||||
      responses:
 | 
			
		||||
        401:
 | 
			
		||||
          description: "Unauthorized"
 | 
			
		||||
        404:
 | 
			
		||||
          description: "Not found"
 | 
			
		||||
        200:
 | 
			
		||||
          description: "OK"
 | 
			
		||||
        422:
 | 
			
		||||
          description: "Unprocessable entity (validation errors)"
 | 
			
		||||
        400:
 | 
			
		||||
          description: "transition cannot be applyed"
 | 
			
		||||
 | 
			
		||||
  /1.0/calendar/calendar-range/{id}.json:
 | 
			
		||||
    get:
 | 
			
		||||
@@ -70,6 +120,56 @@ paths:
 | 
			
		||||
          description: "not found"
 | 
			
		||||
        401:
 | 
			
		||||
          description: "Unauthorized"
 | 
			
		||||
    patch:
 | 
			
		||||
      tags:
 | 
			
		||||
        - calendar
 | 
			
		||||
      summary: update a calendar range
 | 
			
		||||
      requestBody:
 | 
			
		||||
        required: true
 | 
			
		||||
        content:
 | 
			
		||||
          application/json:
 | 
			
		||||
            schema:
 | 
			
		||||
              type: object
 | 
			
		||||
              properties:
 | 
			
		||||
                user:
 | 
			
		||||
                  $ref: '#/components/schemas/User'
 | 
			
		||||
                startDate:
 | 
			
		||||
                  $ref: '#/components/schemas/Date'
 | 
			
		||||
                endDate:
 | 
			
		||||
                  $ref: '#/components/schemas/Date'
 | 
			
		||||
      responses:
 | 
			
		||||
        401:
 | 
			
		||||
          description: "Unauthorized"
 | 
			
		||||
        404:
 | 
			
		||||
          description: "Not found"
 | 
			
		||||
        200:
 | 
			
		||||
          description: "OK"
 | 
			
		||||
        422:
 | 
			
		||||
          description: "Unprocessable entity (validation errors)"
 | 
			
		||||
        400:
 | 
			
		||||
          description: "transition cannot be applyed"
 | 
			
		||||
    delete:
 | 
			
		||||
      tags:
 | 
			
		||||
        - calendar
 | 
			
		||||
      summary: "Remove a calendar range"
 | 
			
		||||
      parameters:
 | 
			
		||||
        - name: id
 | 
			
		||||
          in: path
 | 
			
		||||
          required: true
 | 
			
		||||
          description: The calendar range id
 | 
			
		||||
          schema:
 | 
			
		||||
            type: integer
 | 
			
		||||
            format: integer
 | 
			
		||||
            minimum: 1
 | 
			
		||||
      responses:
 | 
			
		||||
        401:
 | 
			
		||||
          description: "Unauthorized"
 | 
			
		||||
        404:
 | 
			
		||||
          description: "Not found"
 | 
			
		||||
        200:
 | 
			
		||||
          description: "OK"
 | 
			
		||||
        422:
 | 
			
		||||
          description: "object with validation errors"
 | 
			
		||||
  
 | 
			
		||||
  /1.0/calendar/calendar-range-available.json:
 | 
			
		||||
    get:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
// this file loads all assets from the Chill calendar bundle
 | 
			
		||||
module.exports = function(encore, entries) {
 | 
			
		||||
    entries.push(__dirname + '/Resources/public/chill/index.js');
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    encore.addAliases({
 | 
			
		||||
        ChillCalendarAssets: __dirname + '/Resources/public'
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    encore.addEntry('vue_calendar', __dirname + '/Resources/public/vuejs/Calendar/index.js');
 | 
			
		||||
    encore.addEntry('vue_mycalendarrange', __dirname + '/Resources/public/vuejs/MyCalendarRange/index.js');
 | 
			
		||||
    encore.addEntry('page_calendar', __dirname + '/Resources/public/chill/index.js');
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
Calendar: Rendez-vous
 | 
			
		||||
Calendar list: Liste des rendez-vous
 | 
			
		||||
My calendar list: Mes rendez-vous
 | 
			
		||||
There is no calendar items.: Il n'y a pas de rendez-vous
 | 
			
		||||
Remove calendar item: Supprimer le rendez-vous
 | 
			
		||||
Are you sure you want to remove the calendar item?: Êtes-vous sûr de vouloir supprimer le rendez-vous?
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,8 @@ class ApiController extends AbstractCRUDController
 | 
			
		||||
                return $this->entityPut('_entity', $request, $id, $_format);
 | 
			
		||||
            case Request::METHOD_POST:
 | 
			
		||||
                return $this->entityPostAction('_entity', $request, $id, $_format);
 | 
			
		||||
            case Request::METHOD_DELETE:
 | 
			
		||||
                return $this->entityDelete('_entity', $request, $id, $_format);
 | 
			
		||||
            default:
 | 
			
		||||
                throw new \Symfony\Component\HttpFoundation\Exception\BadRequestException("This method is not implemented");
 | 
			
		||||
        }
 | 
			
		||||
@@ -217,6 +219,54 @@ class ApiController extends AbstractCRUDController
 | 
			
		||||
            $this->getContextForSerializationPostAlter($action, $request, $_format, $entity)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public function entityDelete($action, Request $request, $id, string $_format): Response
 | 
			
		||||
    {
 | 
			
		||||
        $entity = $this->getEntity($action, $id, $request, $_format);
 | 
			
		||||
 | 
			
		||||
        if (NULL === $entity) {
 | 
			
		||||
            throw $this->createNotFoundException(sprintf("The %s with id %s "
 | 
			
		||||
                . "is not found", $this->getCrudName(), $id));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $response = $this->checkACL($action, $request, $_format, $entity);
 | 
			
		||||
        if ($response instanceof Response) {
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $response = $this->onPostCheckACL($action, $request, $_format, $entity);
 | 
			
		||||
        if ($response instanceof Response) {
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $response = $this->onBeforeSerialize($action, $request, $_format, $entity);
 | 
			
		||||
        if ($response instanceof Response) {
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $errors = $this->validate($action, $request, $_format, $entity);
 | 
			
		||||
 | 
			
		||||
        $response = $this->onAfterValidation($action, $request, $_format, $entity, $errors);
 | 
			
		||||
        if ($response instanceof Response) {
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($errors->count() > 0) {
 | 
			
		||||
            $response = $this->json($errors);
 | 
			
		||||
            $response->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY);
 | 
			
		||||
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->getDoctrine()->getManager()->remove($entity);
 | 
			
		||||
        $this->getDoctrine()->getManager()->flush();
 | 
			
		||||
 | 
			
		||||
        $response = $this->onAfterFlush($action, $request, $_format, $entity, $errors);
 | 
			
		||||
        if ($response instanceof Response) {
 | 
			
		||||
            return $response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->json(Response::HTTP_OK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function onAfterValidation(string $action, Request $request, string $_format, $entity, ConstraintViolationListInterface $errors, array $more = []): ?Response
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -1141,7 +1141,7 @@ class CRUDController extends AbstractController
 | 
			
		||||
     */
 | 
			
		||||
    protected function getPaginatorFactory(): PaginatorFactory
 | 
			
		||||
    {
 | 
			
		||||
        return $this->container->get(PaginatorFactory::class);
 | 
			
		||||
        return $this->container->get('chill_main.paginator_factory');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -1196,7 +1196,7 @@ class CRUDController extends AbstractController
 | 
			
		||||
        return \array_merge(
 | 
			
		||||
            parent::getSubscribedServices(),
 | 
			
		||||
            [
 | 
			
		||||
                PaginatorFactory::class => PaginatorFactory::class,
 | 
			
		||||
                'chill_main.paginator_factory' => PaginatorFactory::class,
 | 
			
		||||
                'translator' => TranslatorInterface::class,
 | 
			
		||||
                AuthorizationHelper::class => AuthorizationHelper::class,
 | 
			
		||||
                EventDispatcherInterface::class => EventDispatcherInterface::class,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace Chill\MainBundle;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
 | 
			
		||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
 | 
			
		||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
 | 
			
		||||
use Chill\MainBundle\DependencyInjection\CompilerPass\SearchableServicesCompilerPass;
 | 
			
		||||
@@ -23,6 +24,10 @@ class ChillMainBundle extends Bundle
 | 
			
		||||
    public function build(ContainerBuilder $container)
 | 
			
		||||
    {
 | 
			
		||||
        parent::build($container);
 | 
			
		||||
 | 
			
		||||
        $container->registerForAutoconfiguration(LocalMenuBuilderInterface::class)
 | 
			
		||||
            ->addTag('chill.menu_builder');
 | 
			
		||||
 | 
			
		||||
        $container->addCompilerPass(new SearchableServicesCompilerPass());
 | 
			
		||||
        $container->addCompilerPass(new ConfigConsistencyCompilerPass());
 | 
			
		||||
        $container->addCompilerPass(new TimelineCompilerClass());
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Load fixtures users into database
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * create a user for each permission_group and center.
 | 
			
		||||
 * username and password are identicals.
 | 
			
		||||
 *
 | 
			
		||||
@@ -28,12 +28,12 @@ class LoadUsers extends AbstractFixture implements OrderedFixtureInterface, Cont
 | 
			
		||||
     * @var ContainerInterface
 | 
			
		||||
     */
 | 
			
		||||
    private $container;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public function getOrder()
 | 
			
		||||
    {
 | 
			
		||||
        return 1000;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public static $refs = array(
 | 
			
		||||
        'center a_social' => array(
 | 
			
		||||
            'groupCenterRefs' => ['centerA_permission_group_social']
 | 
			
		||||
@@ -54,10 +54,10 @@ class LoadUsers extends AbstractFixture implements OrderedFixtureInterface, Cont
 | 
			
		||||
            'groupCenterRefs' => ['centerB_permission_group_direction']
 | 
			
		||||
        ),
 | 
			
		||||
        'multi_center' => array(
 | 
			
		||||
            'groupCenterRefs' => ['centerA_permission_group_social', 
 | 
			
		||||
            'groupCenterRefs' => ['centerA_permission_group_social',
 | 
			
		||||
                'centerB_permission_group_social']
 | 
			
		||||
        )
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    public function load(ObjectManager $manager)
 | 
			
		||||
@@ -67,11 +67,11 @@ class LoadUsers extends AbstractFixture implements OrderedFixtureInterface, Cont
 | 
			
		||||
            $user = new User();
 | 
			
		||||
 | 
			
		||||
            $defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            $encoderFactory = new EncoderFactory([
 | 
			
		||||
                User::class => $defaultEncoder
 | 
			
		||||
            ]);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            $user
 | 
			
		||||
                ->setUsername($username)
 | 
			
		||||
                ->setPassword($encoderFactory
 | 
			
		||||
@@ -84,7 +84,7 @@ class LoadUsers extends AbstractFixture implements OrderedFixtureInterface, Cont
 | 
			
		||||
            foreach ($params['groupCenterRefs'] as $groupCenterRef) {
 | 
			
		||||
                $user->addGroupCenter($this->getReference($groupCenterRef));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            echo 'Creating user ' . $username ."... \n";
 | 
			
		||||
            $manager->persist($user);
 | 
			
		||||
            $this->addReference($username, $user);
 | 
			
		||||
@@ -98,7 +98,7 @@ class LoadUsers extends AbstractFixture implements OrderedFixtureInterface, Cont
 | 
			
		||||
        if (NULL === $container) {
 | 
			
		||||
            throw new \LogicException('$container should not be null');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        $this->container = $container;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -78,6 +78,7 @@ export default {
 | 
			
		||||
@import 'ChillMainAssets/module/bootstrap/shared';
 | 
			
		||||
@import 'ChillPersonAssets/chill/scss/mixins';
 | 
			
		||||
 | 
			
		||||
div#accompanying-course {
 | 
			
		||||
   span.multiselect__tag {
 | 
			
		||||
      @include badge_social_issue;
 | 
			
		||||
      background: $chill-l-gray;
 | 
			
		||||
@@ -93,6 +94,7 @@ export default {
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <h2>{{ $t('household_members_editor.concerned.title') }}</h2>
 | 
			
		||||
  <h2 class="mt-4">{{ $t('household_members_editor.concerned.title') }}</h2>
 | 
			
		||||
 | 
			
		||||
  <h3 v-if="needsPositionning">
 | 
			
		||||
    {{ $t('household_members_editor.concerned.persons_to_positionnate') }}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,71 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <h2>{{ $t('household_members_editor.household_part') }}</h2>
 | 
			
		||||
 | 
			
		||||
  <h2 class="mt-4">{{ $t('household_members_editor.household_part') }}</h2>
 | 
			
		||||
 | 
			
		||||
  <div v-if="hasHousehold">
 | 
			
		||||
 | 
			
		||||
    <div class="flex-table">
 | 
			
		||||
       <div class="item-bloc">
 | 
			
		||||
          <household-render-box :household="household" :isAddressMultiline="true"></household-render-box>
 | 
			
		||||
       </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div v-if="isHouseholdNew && !hasHouseholdAddress">
 | 
			
		||||
 | 
			
		||||
      <h3>{{ $t('household_members_editor.household.where_live_the_household') }}</h3>
 | 
			
		||||
 | 
			
		||||
      <div v-if="filterAddressesSuggestion.length > 0" class="flex-table householdAddressSuggestionList">
 | 
			
		||||
        <div v-for="a in filterAddressesSuggestion" class="item-bloc">
 | 
			
		||||
          <address-render-box :address="a"></address-render-box>
 | 
			
		||||
           <ul class="record_actions">
 | 
			
		||||
              <li>
 | 
			
		||||
                  <button class="btn btn-action" @click="setHouseholdAddress(a)">
 | 
			
		||||
                     {{ $t('household_members_editor.household.household_live_to_this_address') }}
 | 
			
		||||
                  </button>
 | 
			
		||||
               </li>
 | 
			
		||||
           </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div v-else>
 | 
			
		||||
        <span class="chill-no-data-statement">{{ $t('household_members_editor.household.no_suggestions') }}</span>
 | 
			
		||||
      <div v-if="hasAddressSuggestion" class="householdAddressSuggestion my-5">
 | 
			
		||||
          <h4 class="mb-3">
 | 
			
		||||
             {{ $t('household_members_editor.household.where_live_the_household') }}
 | 
			
		||||
          </h4>
 | 
			
		||||
          <div class="accordion" id="addressSuggestions">
 | 
			
		||||
             <div class="accordion-item">
 | 
			
		||||
                <h2 class="accordion-header" id="heading_address_suggestions">
 | 
			
		||||
                   <button v-if="!showAddressSuggestion"
 | 
			
		||||
                      class="accordion-button collapsed"
 | 
			
		||||
                      type="button"
 | 
			
		||||
                      data-bs-toggle="collapse"
 | 
			
		||||
                      aria-expanded="false"
 | 
			
		||||
                      @click="toggleAddressSuggestion">
 | 
			
		||||
                      {{ $tc('household_members_editor.show_household_suggestion', countAddressSuggestion) }}
 | 
			
		||||
                   </button>
 | 
			
		||||
                   <button v-if="showAddressSuggestion"
 | 
			
		||||
                      class="accordion-button"
 | 
			
		||||
                      type="button"
 | 
			
		||||
                      data-bs-toggle="collapse"
 | 
			
		||||
                      aria-expanded="true"
 | 
			
		||||
                      @click="toggleAddressSuggestion">
 | 
			
		||||
                      {{ $t('household_members_editor.hide_household_suggestion') }}
 | 
			
		||||
                   </button>
 | 
			
		||||
                </h2>
 | 
			
		||||
                <div class="accordion-collapse" id="collapse_address_suggestions"
 | 
			
		||||
                   aria-labelledby="heading_address_suggestions" data-bs-parent="#addressSuggestions">
 | 
			
		||||
                   <div v-if="showAddressSuggestion">
 | 
			
		||||
                      <div class="flex-table householdAddressSuggestionList">
 | 
			
		||||
                         <div v-for="a in filterAddressesSuggestion" class="item-bloc">
 | 
			
		||||
                            <div class="float-button bottom">
 | 
			
		||||
                               <div class="box">
 | 
			
		||||
                                  <div class="action">
 | 
			
		||||
                                     <ul class="record_actions">
 | 
			
		||||
                                        <li>
 | 
			
		||||
                                           <button class="btn btn-sm btn-choose" @click="setHouseholdAddress(a)">
 | 
			
		||||
                                              {{ $t('household_members_editor.household.household_live_to_this_address') }}
 | 
			
		||||
                                           </button>
 | 
			
		||||
                                        </li>
 | 
			
		||||
                                     </ul>
 | 
			
		||||
                                  </div>
 | 
			
		||||
                                  <ul class="list-content fa-ul">
 | 
			
		||||
                                     <li>
 | 
			
		||||
                                        <i class="fa fa-li fa-map-marker"></i>
 | 
			
		||||
                                        <address-render-box :address="a"></address-render-box>
 | 
			
		||||
                                     </li>
 | 
			
		||||
                                  </ul>
 | 
			
		||||
                               </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                         </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                   </div>
 | 
			
		||||
                </div>
 | 
			
		||||
             </div>
 | 
			
		||||
          </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <ul class="record_actions">
 | 
			
		||||
@@ -39,8 +80,8 @@
 | 
			
		||||
          </add-address>
 | 
			
		||||
        </li>
 | 
			
		||||
      </ul>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div v-if="isHouseholdNew && hasHouseholdAddress">
 | 
			
		||||
      <ul class="record_actions">
 | 
			
		||||
        <li >
 | 
			
		||||
@@ -49,34 +90,15 @@
 | 
			
		||||
          </button>
 | 
			
		||||
        </li>
 | 
			
		||||
      </ul>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
  <div v-else-if="isForceLeaveWithoutHousehold">
 | 
			
		||||
      {{ $t('household_members_editor.household.will_leave_any_household') }}
 | 
			
		||||
  </div>
 | 
			
		||||
  <div v-else>
 | 
			
		||||
    <div class="alert alert-info">{{ $t('household_members_editor.household.no_household_choose_one') }}</div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div v-else class="alert alert-info">{{ $t('household_members_editor.household.no_household_choose_one') }}</div>
 | 
			
		||||
 | 
			
		||||
  <ul v-if="allowChangeHousehold" class="record_actions">
 | 
			
		||||
    <li v-if="!showHouseholdSuggestion" class="cancel">
 | 
			
		||||
      <button
 | 
			
		||||
        class="btn btn-misc"
 | 
			
		||||
        @click="toggleHouseholdSuggestion"
 | 
			
		||||
      ><i class="fa fa-fw fa-caret-right"></i>
 | 
			
		||||
        {{ $tc('household_members_editor.show_household_suggestion',
 | 
			
		||||
          countHouseholdSuggestion) }}
 | 
			
		||||
      </button>
 | 
			
		||||
    </li>
 | 
			
		||||
    <li v-if="showHouseholdSuggestion && hasHouseholdSuggestion" class="cancel">
 | 
			
		||||
      <button
 | 
			
		||||
        class="btn btn-misc"
 | 
			
		||||
        @click="toggleHouseholdSuggestion"
 | 
			
		||||
      ><i class="fa fa-fw fa-caret-down"></i>
 | 
			
		||||
        {{ $t('household_members_editor.hide_household_suggestion') }}
 | 
			
		||||
      </button>
 | 
			
		||||
    </li>
 | 
			
		||||
    <li v-if="allowHouseholdCreate">
 | 
			
		||||
      <button class="btn btn-create" @click="createHousehold">
 | 
			
		||||
        {{ $t('household_members_editor.household.create_household') }}
 | 
			
		||||
@@ -99,29 +121,54 @@
 | 
			
		||||
    </li>
 | 
			
		||||
  </ul>
 | 
			
		||||
 | 
			
		||||
  <div class="householdSuggestions">
 | 
			
		||||
    <div v-if="showHouseholdSuggestion && hasHouseholdSuggestion">
 | 
			
		||||
 | 
			
		||||
      <h3>{{ $t('household_members_editor.suggestions') }}</h3>
 | 
			
		||||
      <p>{{ $t('household_members_editor.household_for_participants_accompanying_period') }}:</p>
 | 
			
		||||
 | 
			
		||||
      <div class="flex-table householdSuggestionList">
 | 
			
		||||
         <div v-for="h in filterHouseholdSuggestionByAccompanyingPeriod" class="item-bloc">
 | 
			
		||||
          <household-render-box :household="h"></household-render-box>
 | 
			
		||||
          <ul class="record_actions">
 | 
			
		||||
            <li>
 | 
			
		||||
              <button class="btn btn-sm btn-choose" @click="selectHousehold(h)">
 | 
			
		||||
                {{ $t('household_members_editor.select_household') }}
 | 
			
		||||
              </button>
 | 
			
		||||
            </li>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
   <div v-if="hasHouseholdSuggestion" class="householdSuggestions my-5">
 | 
			
		||||
      <h4 class="mb-3">
 | 
			
		||||
         {{ $t('household_members_editor.household_for_participants_accompanying_period') }} :
 | 
			
		||||
      </h4>
 | 
			
		||||
      <div class="accordion" id="householdSuggestions">
 | 
			
		||||
         <div class="accordion-item">
 | 
			
		||||
            <h2 class="accordion-header" id="heading_household_suggestions">
 | 
			
		||||
               <button v-if="!showHouseholdSuggestion"
 | 
			
		||||
                  class="accordion-button collapsed"
 | 
			
		||||
                  type="button"
 | 
			
		||||
                  data-bs-toggle="collapse"
 | 
			
		||||
                  aria-expanded="false"
 | 
			
		||||
                  @click="toggleHouseholdSuggestion">
 | 
			
		||||
                  {{ $tc('household_members_editor.show_household_suggestion', countHouseholdSuggestion) }}
 | 
			
		||||
               </button>
 | 
			
		||||
               <button v-if="showHouseholdSuggestion"
 | 
			
		||||
                  class="accordion-button"
 | 
			
		||||
                  type="button"
 | 
			
		||||
                  data-bs-toggle="collapse"
 | 
			
		||||
                  aria-expanded="true"
 | 
			
		||||
                  @click="toggleHouseholdSuggestion">
 | 
			
		||||
                  {{ $t('household_members_editor.hide_household_suggestion') }}
 | 
			
		||||
               </button>
 | 
			
		||||
               <!-- disabled bootstrap behaviour:  data-bs-target="#collapse_household_suggestions" aria-controls="collapse_household_suggestions" -->
 | 
			
		||||
            </h2>
 | 
			
		||||
            <div class="accordion-collapse" id="collapse_household_suggestions"
 | 
			
		||||
                 aria-labelledby="heading_household_suggestions" data-bs-parent="#householdSuggestions">
 | 
			
		||||
               <div v-if="showHouseholdSuggestion">
 | 
			
		||||
                  <div class="flex-table householdSuggestionList">
 | 
			
		||||
                     <div v-for="h in filterHouseholdSuggestionByAccompanyingPeriod" class="item-bloc">
 | 
			
		||||
                        <household-render-box :household="h"></household-render-box>
 | 
			
		||||
                        <ul class="record_actions">
 | 
			
		||||
                           <li>
 | 
			
		||||
                              <button class="btn btn-sm btn-choose" @click="selectHousehold(h)">
 | 
			
		||||
                                 {{ $t('household_members_editor.select_household') }}
 | 
			
		||||
                              </button>
 | 
			
		||||
                           </li>
 | 
			
		||||
                        </ul>
 | 
			
		||||
                     </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
               </div>
 | 
			
		||||
            </div>
 | 
			
		||||
         </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
   </div>
 | 
			
		||||
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { mapGetters, mapState } from 'vuex';
 | 
			
		||||
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
 | 
			
		||||
@@ -154,12 +201,12 @@ export default {
 | 
			
		||||
          },
 | 
			
		||||
          button: {
 | 
			
		||||
            text:  {
 | 
			
		||||
              create: null,
 | 
			
		||||
              create: 'household_members_editor.household.or_create_new_address',
 | 
			
		||||
              edit: null,
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          title: {
 | 
			
		||||
            create: null,
 | 
			
		||||
            create: 'household_members_editor.household.create_new_address',
 | 
			
		||||
            edit: null,
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
@@ -173,11 +220,14 @@ export default {
 | 
			
		||||
      'hasHouseholdSuggestion',
 | 
			
		||||
      'countHouseholdSuggestion',
 | 
			
		||||
      'filterHouseholdSuggestionByAccompanyingPeriod',
 | 
			
		||||
      'hasAddressSuggestion',
 | 
			
		||||
      'countAddressSuggestion',
 | 
			
		||||
      'filterAddressesSuggestion',
 | 
			
		||||
      'hasHouseholdAddress',
 | 
			
		||||
    ]),
 | 
			
		||||
    ...mapState([
 | 
			
		||||
      'showHouseholdSuggestion',
 | 
			
		||||
      'showAddressSuggestion'
 | 
			
		||||
    ]),
 | 
			
		||||
    household() {
 | 
			
		||||
      return this.$store.state.household;
 | 
			
		||||
@@ -218,8 +268,12 @@ export default {
 | 
			
		||||
    toggleHouseholdSuggestion() {
 | 
			
		||||
      this.$store.commit('toggleHouseholdSuggestion');
 | 
			
		||||
    },
 | 
			
		||||
    toggleAddressSuggestion() {
 | 
			
		||||
      this.$store.commit('toggleAddressSuggestion');
 | 
			
		||||
    },
 | 
			
		||||
    selectHousehold(h) {
 | 
			
		||||
      this.$store.dispatch('selectHousehold', h);
 | 
			
		||||
      this.toggleHouseholdSuggestion();
 | 
			
		||||
    },
 | 
			
		||||
    removeHousehold() {
 | 
			
		||||
      this.$store.dispatch('removeHousehold');
 | 
			
		||||
@@ -236,7 +290,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    removeHouseholdAddress() {
 | 
			
		||||
      this.$store.commit('removeHouseholdAddress');
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -246,12 +300,15 @@ export default {
 | 
			
		||||
 | 
			
		||||
div#household_members_editor div,
 | 
			
		||||
div.householdSuggestionList {
 | 
			
		||||
   &.flex-table div.item-bloc div.item-row div.item-col {
 | 
			
		||||
      &:first-child {
 | 
			
		||||
         width: 25%;
 | 
			
		||||
      }
 | 
			
		||||
      &:last-child {
 | 
			
		||||
         display: initial;
 | 
			
		||||
   &.flex-table {
 | 
			
		||||
      margin: 0;
 | 
			
		||||
      div.item-bloc div.item-row div.item-col {
 | 
			
		||||
         &:first-child {
 | 
			
		||||
            width: 25%;
 | 
			
		||||
         }
 | 
			
		||||
         &:last-child {
 | 
			
		||||
            display: initial;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,14 +7,16 @@ const appMessages = {
 | 
			
		||||
      household: {
 | 
			
		||||
        no_household_choose_one: "Aucun ménage de destination. Choisissez un ménage. Les usagers concernés par la modification apparaitront ensuite.",
 | 
			
		||||
        new_household: "Nouveau ménage",
 | 
			
		||||
        create_household: "Créer un ménage de destination",
 | 
			
		||||
        create_household: "Créer un nouveau ménage de destination",
 | 
			
		||||
        search_household: "Chercher un ménage",
 | 
			
		||||
        will_leave_any_household: "Ne rejoignent pas de ménage",
 | 
			
		||||
        leave_without_household: "Sans nouveau ménage",
 | 
			
		||||
        where_live_the_household: "À quelle adresse habite ce ménage ?",
 | 
			
		||||
        household_live_to_this_address: "Le ménage habite cette adresse",
 | 
			
		||||
        household_live_to_this_address: "Sélectionner l'adresse",
 | 
			
		||||
        no_suggestions: "Aucune adresse à suggérer",
 | 
			
		||||
        delete_this_address: "Supprimer cette adresse",
 | 
			
		||||
        create_new_address: "Créer une nouvelle adresse",
 | 
			
		||||
        or_create_new_address: "Ou créer une nouvelle adresse",
 | 
			
		||||
      },
 | 
			
		||||
      concerned: {
 | 
			
		||||
        title: "Nouveaux membres du ménage",
 | 
			
		||||
@@ -36,8 +38,8 @@ const appMessages = {
 | 
			
		||||
      suggestions: "Suggestions",
 | 
			
		||||
      hide_household_suggestion: "Masquer les suggestions",
 | 
			
		||||
      show_household_suggestion: 'Aucune suggestion | Afficher une suggestion | Afficher {count} suggestions',
 | 
			
		||||
      household_for_participants_accompanying_period: "Ces ménages partagent le même parcours",
 | 
			
		||||
      select_household: "Sélectionner",
 | 
			
		||||
      household_for_participants_accompanying_period: "Des ménages partagent le même parcours",
 | 
			
		||||
      select_household: "Sélectionner le ménage",
 | 
			
		||||
      dates_title: "Période de validité",
 | 
			
		||||
      dates: {
 | 
			
		||||
        start_date: "Début de validité",
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ const store = createStore({
 | 
			
		||||
    householdSuggestionByAccompanyingPeriod: [],
 | 
			
		||||
    showHouseholdSuggestion: window.household_members_editor_expand_suggestions === 1,
 | 
			
		||||
    addressesSuggestion: [],
 | 
			
		||||
    showAddressSuggestion: true,
 | 
			
		||||
    warnings: [],
 | 
			
		||||
    errors: []
 | 
			
		||||
  },
 | 
			
		||||
@@ -73,6 +74,12 @@ const store = createStore({
 | 
			
		||||
        .filter(h => h.id !== state.household.id)
 | 
			
		||||
        ;
 | 
			
		||||
    },
 | 
			
		||||
    hasAddressSuggestion(state, getters) {
 | 
			
		||||
      return getters.filterAddressesSuggestion.length > 0;
 | 
			
		||||
    },
 | 
			
		||||
    countAddressSuggestion(state, getters) {
 | 
			
		||||
      return getters.filterAddressesSuggestion.length;
 | 
			
		||||
    },
 | 
			
		||||
    filterAddressesSuggestion(state) {
 | 
			
		||||
      if (state.household === null) {
 | 
			
		||||
        return state.addressesSuggestion;
 | 
			
		||||
@@ -260,6 +267,9 @@ const store = createStore({
 | 
			
		||||
    toggleHouseholdSuggestion(state) {
 | 
			
		||||
      state.showHouseholdSuggestion = !state.showHouseholdSuggestion;
 | 
			
		||||
    },
 | 
			
		||||
    toggleAddressSuggestion(state) {
 | 
			
		||||
      state.showAddressSuggestion = !state.showAddressSuggestion;
 | 
			
		||||
    },
 | 
			
		||||
    setWarnings(state, warnings) {
 | 
			
		||||
      state.warnings = warnings;
 | 
			
		||||
      // reset errors, which should come from servers
 | 
			
		||||
@@ -327,7 +337,7 @@ const store = createStore({
 | 
			
		||||
      commit('forceLeaveWithoutHousehold');
 | 
			
		||||
      dispatch('computeWarnings');
 | 
			
		||||
    },
 | 
			
		||||
    selectHousehold({ commit }, h) {
 | 
			
		||||
    selectHousehold({ commit, dispatch }, h) {
 | 
			
		||||
      commit('selectHousehold', h);
 | 
			
		||||
      dispatch('computeWarnings');
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -115,6 +115,17 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
                'icon' => 'tasks'
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
        $menu->addChild("My calendar list", [
 | 
			
		||||
                'route' => 'chill_calendar_calendar_list',
 | 
			
		||||
                'routeParameters' => [
 | 
			
		||||
                    'user_id' => $user->getId(),
 | 
			
		||||
                ]
 | 
			
		||||
            ])
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => -9,
 | 
			
		||||
                'icon' => 'tasks'
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
        $menu->addChild("My aside activities", [
 | 
			
		||||
                'route' => 'chill_crud_aside_activity_index'
 | 
			
		||||
 
 | 
			
		||||
 Submodule tests/app updated: 8839b431f2...bd95d3c96a
									
								
							
		Reference in New Issue
	
	Block a user