diff --git a/.env b/.env deleted file mode 100644 index 619f471ca..000000000 --- a/.env +++ /dev/null @@ -1,64 +0,0 @@ -## -## Manually dump .env files in .env.local.php with -## `$ composer symfony:dump-env prod` -## - -## Project environment -APP_ENV=dev - -## Enable debug -APP_DEBUG=true - -## Locale -LOCALE=fr - -## Framework secret -APP_SECRET=ThisTokenIsNotSoSecretChangeIt - -## Symfony/swiftmailer -MAILER_TRANSPORT=smtp -MAILER_HOST=smtp -MAILER_PORT=1025 -MAILER_CRYPT= -MAILER_AUTH= -MAILER_USER= -MAILER_PASSWORD= -MAILER_URL=${MAILER_TRANSPORT}://${MAILER_HOST}:${MAILER_PORT}?encryption=${MAILER_CRYPT}&auth_mode=${MAILER_AUTH}&username=${MAILER_USER}&password=${MAILER_PASSWORD} - -## Notifications -NOTIFICATION_HOST=localhost:8001 -NOTIFICATION_FROM_EMAIL=admin@chill.social -NOTIFICATION_FROM_NAME=Chill - -## Gelf -GELF_HOST=gelf -GELF_PORT=12201 - -## OVH OpenStack Storage User/Role -OS_USERNAME= -OS_PASSWORD= -OS_TENANT_ID= -OS_REGION_NAME=GRA -OS_AUTH_URL=https://auth.cloud.ovh.net/v2.0/ - -## OVH OpenStack Storage Container -ASYNC_UPLOAD_TEMP_URL_KEY= -ASYNC_UPLOAD_TEMP_URL_BASE_PATH= -ASYNC_UPLOAD_TEMP_URL_CONTAINER= - -## Redis Cache -REDIS_HOST=redis -REDIS_PORT=6379 -REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} - -## Twilio -TWILIO_SID=~ -TWILIO_SECRET=~ - -## DOCKER IMAGES REGISTRY -#IMAGE_PHP= -#IMAGE_NGINX= - -## DOCKER IMAGES VERSION -#VERSION=test -VERSION=prod diff --git a/CHANGELOG.md b/CHANGELOG.md index fcf514de1..27d5e0bf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,23 @@ and this project adheres to [activity] correct associated persons by considering only open participations (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/476) + +## Test releases + +### test release 2022-02-14 + +* AddPersons: remove ul-li html tags from AddPersons (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/419) +* [doc-generator] do not set required fields for mainPerson, person1, person2 (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement#456) +* [doc-generation] add age and obele in the mainPerson, person1 and person2 list + add obele in person renderString if addAge (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/370) +* [person] accompanying course work: fix on-the-fly update of thirdParty +* fix normalisation of accompanying course requestor api (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/378) * [person] add a returnPath when clicking on some Person or ThirdParty badge (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/427) * [person] accompanying course work: fix on-the-fly update of thirdParty * [on-the-fly] close modal only after validation * [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433) * change order for accompanying course work list +* [parcours]: Mes parcours brouillon added to user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/440) +* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414) * [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432) * [household]: display address of current household (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/415) * ajoute un ordre dans les localisation (api) @@ -27,8 +39,9 @@ and this project adheres to * [person]: create person and household added to button dropdown (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/454) * display full address in address.text in normalization. Adapt AddressRenderBox * [address]: Correction residential address 'depuis le' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/459) - -## Test releases +* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414) +* [Thirdparty_contact]: address blurred if confidential in view page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/450) +* [homepage_widget]: If no sender then display as 'notification automatique' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/435) ### test release 2021-02-01 diff --git a/phpstan-deprecations.neon b/phpstan-deprecations.neon index b41a746b9..7489d4d80 100644 --- a/phpstan-deprecations.neon +++ b/phpstan-deprecations.neon @@ -408,24 +408,6 @@ parameters: count: 1 path: src/Bundle/ChillCustomFieldsBundle/Form/CustomFieldsGroupType.php - - - message: - """ - #^Call to deprecated method getReachableScopes\\(\\) of class Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\: - Use getReachableCircles$# - """ - count: 1 - path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php - - - - message: - """ - #^Parameter \\$translator of method Chill\\\\DocStoreBundle\\\\Controller\\\\DocumentPersonController\\:\\:__construct\\(\\) has typehint with deprecated interface Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\: - since Symfony 4\\.2, use Symfony\\\\Contracts\\\\Translation\\\\TranslatorInterface instead$# - """ - count: 1 - path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php - - message: """ diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue index 45483dc95..7ec62d07d 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/ConcernedGroups.vue @@ -19,14 +19,18 @@ - - + diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php index a5ad5cfa1..199f88c60 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php @@ -13,7 +13,9 @@ namespace Chill\DocStoreBundle\Controller; use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument; use Chill\DocStoreBundle\Form\AccompanyingCourseDocumentType; +use Chill\DocStoreBundle\Repository\AccompanyingCourseDocumentRepository; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; +use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\PersonBundle\Entity\AccompanyingPeriod; use DateTime; @@ -29,20 +31,15 @@ use Symfony\Contracts\Translation\TranslatorInterface; */ class DocumentAccompanyingCourseController extends AbstractController { - /** - * @var AuthorizationHelper - */ - protected $authorizationHelper; + protected AuthorizationHelper $authorizationHelper; - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; + protected EventDispatcherInterface $eventDispatcher; - /** - * @var TranslatorInterface - */ - protected $translator; + protected TranslatorInterface $translator; + + private AccompanyingCourseDocumentRepository $courseRepository; + + private PaginatorFactory $paginatorFactory; /** * DocumentAccompanyingCourseController constructor. @@ -50,11 +47,15 @@ class DocumentAccompanyingCourseController extends AbstractController public function __construct( TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, - AuthorizationHelper $authorizationHelper + AuthorizationHelper $authorizationHelper, + PaginatorFactory $paginatorFactory, + AccompanyingCourseDocumentRepository $courseRepository ) { $this->translator = $translator; $this->eventDispatcher = $eventDispatcher; $this->authorizationHelper = $authorizationHelper; + $this->paginatorFactory = $paginatorFactory; + $this->courseRepository = $courseRepository; } /** @@ -130,11 +131,15 @@ class DocumentAccompanyingCourseController extends AbstractController $this->denyAccessUnlessGranted(AccompanyingCourseDocumentVoter::SEE, $course); - $documents = $em - ->getRepository('ChillDocStoreBundle:AccompanyingCourseDocument') + $total = $this->courseRepository->countByCourse($course); + $pagination = $this->paginatorFactory->create($total); + + $documents = $this->courseRepository ->findBy( ['course' => $course], - ['date' => 'DESC'] + ['date' => 'DESC'], + $pagination->getItemsPerPage(), + $pagination->getCurrentPageFirstItemNumber() ); return $this->render( @@ -142,6 +147,7 @@ class DocumentAccompanyingCourseController extends AbstractController [ 'documents' => $documents, 'accompanyingCourse' => $course, + 'pagination' => $pagination, ] ); } diff --git a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php index 5028757bd..fcb3a4958 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php @@ -13,7 +13,8 @@ namespace Chill\DocStoreBundle\Controller; use Chill\DocStoreBundle\Entity\PersonDocument; use Chill\DocStoreBundle\Form\PersonDocumentType; -use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; +use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; +use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Privacy\PrivacyEvent; @@ -24,7 +25,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Class DocumentPersonController. @@ -35,20 +36,15 @@ use Symfony\Component\Translation\TranslatorInterface; */ class DocumentPersonController extends AbstractController { - /** - * @var AuthorizationHelper - */ - protected $authorizationHelper; + protected AuthorizationHelper $authorizationHelper; - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; + protected EventDispatcherInterface $eventDispatcher; - /** - * @var TranslatorInterface - */ - protected $translator; + protected TranslatorInterface $translator; + + private PaginatorFactory $paginatorFactory; + + private PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository; /** * DocumentPersonController constructor. @@ -56,11 +52,15 @@ class DocumentPersonController extends AbstractController public function __construct( TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, - AuthorizationHelper $authorizationHelper + AuthorizationHelper $authorizationHelper, + PaginatorFactory $paginatorFactory, + PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository ) { $this->translator = $translator; $this->eventDispatcher = $eventDispatcher; $this->authorizationHelper = $authorizationHelper; + $this->paginatorFactory = $paginatorFactory; + $this->personDocumentACLAwareRepository = $personDocumentACLAwareRepository; } /** @@ -156,19 +156,15 @@ class DocumentPersonController extends AbstractController $this->denyAccessUnlessGranted(PersonVoter::SEE, $person); - $reachableScopes = $this->authorizationHelper - ->getReachableScopes( - $this->getUser(), - PersonDocumentVoter::SEE, - $person->getCenter() - ); + $total = $this->personDocumentACLAwareRepository->countByPerson($person); + $pagination = $this->paginatorFactory->create($total); - $documents = $em - ->getRepository('ChillDocStoreBundle:PersonDocument') - ->findBy( - ['person' => $person, 'scope' => $reachableScopes], - ['date' => 'DESC'] - ); + $documents = $this->personDocumentACLAwareRepository->findByPerson( + $person, + [], + $pagination->getItemsPerPage(), + $pagination->getCurrentPageFirstItemNumber() + ); $event = new PrivacyEvent($person, [ 'element_class' => PersonDocument::class, @@ -181,6 +177,7 @@ class DocumentPersonController extends AbstractController [ 'documents' => $documents, 'person' => $person, + 'pagination' => $pagination, ] ); } diff --git a/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php b/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php index a3fd04ca3..036a50722 100644 --- a/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php +++ b/src/Bundle/ChillDocStoreBundle/DependencyInjection/ChillDocStoreExtension.php @@ -38,6 +38,7 @@ class ChillDocStoreExtension extends Extension implements PrependExtensionInterf $loader->load('services/menu.yaml'); $loader->load('services/fixtures.yaml'); $loader->load('services/form.yaml'); + $loader->load('services/templating.yaml'); } public function prepend(ContainerBuilder $container) diff --git a/src/Bundle/ChillDocStoreBundle/Entity/Document.php b/src/Bundle/ChillDocStoreBundle/Entity/Document.php index 874a60f0b..e26469573 100644 --- a/src/Bundle/ChillDocStoreBundle/Entity/Document.php +++ b/src/Bundle/ChillDocStoreBundle/Entity/Document.php @@ -11,7 +11,13 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Entity; +use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; +use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; +use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; +use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; +use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait; use Chill\MainBundle\Entity\HasScopeInterface; +use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; @@ -20,8 +26,12 @@ use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\MappedSuperclass */ -class Document implements HasScopeInterface +class Document implements HasScopeInterface, TrackCreationInterface, TrackUpdateInterface { + use TrackCreationTrait; + + use TrackUpdateTrait; + /** * @ORM\ManyToOne(targetEntity="Chill\DocStoreBundle\Entity\DocumentCategory") * @ORM\JoinColumns({ @@ -67,6 +77,11 @@ class Document implements HasScopeInterface */ private $scope; + /** + * @ORM\ManyToOne(targetEntity="Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate") + */ + private $template; + /** * @ORM\Column(type="text") * @Assert\Length( @@ -82,9 +97,6 @@ class Document implements HasScopeInterface */ private $user; - /** - * @return DocumentCategory - */ public function getCategory(): ?DocumentCategory { return $this->category; @@ -115,11 +127,16 @@ class Document implements HasScopeInterface * * @return \Chill\MainBundle\Entity\Scope */ - public function getScope() + public function getScope(): ?Scope { return $this->scope; } + public function getTemplate(): ?DocGeneratorTemplate + { + return $this->template; + } + public function getTitle(): ?string { return $this->title; @@ -165,6 +182,13 @@ class Document implements HasScopeInterface return $this; } + public function setTemplate(?DocGeneratorTemplate $template): self + { + $this->template = $template; + + return $this; + } + public function setTitle(string $title): self { $this->title = $title; diff --git a/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php b/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php index 86e8d350a..bcbd4d707 100644 --- a/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php +++ b/src/Bundle/ChillDocStoreBundle/Form/PersonDocumentType.php @@ -18,10 +18,12 @@ use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillTextareaType; use Chill\MainBundle\Form\Type\ScopePickerType; use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\MainBundle\Security\Resolver\ScopeResolverDispatcher; use Chill\MainBundle\Templating\TranslatableStringHelper; use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ObjectManager; use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; @@ -51,14 +53,25 @@ class PersonDocumentType extends AbstractType */ protected $user; + private ParameterBagInterface $parameterBag; + + private ScopeResolverDispatcher $scopeResolverDispatcher; + public function __construct( - TranslatableStringHelper $translatableStringHelper + TranslatableStringHelper $translatableStringHelper, + ScopeResolverDispatcher $scopeResolverDispatcher, + ParameterBagInterface $parameterBag ) { $this->translatableStringHelper = $translatableStringHelper; + $this->scopeResolverDispatcher = $scopeResolverDispatcher; + $this->parameterBag = $parameterBag; } public function buildForm(FormBuilderInterface $builder, array $options) { + $document = $options['data']; + $isScopeConcerned = $this->scopeResolverDispatcher->isConcerned($document); + $builder ->add('title', TextType::class) ->add('description', ChillTextareaType::class, [ @@ -67,10 +80,6 @@ class PersonDocumentType extends AbstractType ->add('object', StoredObjectType::class, [ 'error_bubbling' => true, ]) - ->add('scope', ScopePickerType::class, [ - 'center' => $options['center'], - 'role' => $options['role'], - ]) ->add('date', ChillDateType::class) ->add('category', EntityType::class, [ 'placeholder' => 'Choose a document category', @@ -84,6 +93,13 @@ class PersonDocumentType extends AbstractType return $entity ? $this->translatableStringHelper->localize($entity->getName()) : ''; }, ]); + + if ($isScopeConcerned && $this->parameterBag->get('chill_main')['acl']['form_show_scopes']) { + $builder->add('scope', ScopePickerType::class, [ + 'center' => $options['center'], + 'role' => $options['role'], + ]); + } } public function configureOptions(OptionsResolver $resolver) diff --git a/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php new file mode 100644 index 000000000..57c898b68 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Repository/AccompanyingCourseDocumentRepository.php @@ -0,0 +1,75 @@ +em = $em; + $this->repository = $em->getRepository(AccompanyingCourseDocument::class); + } + + public function buildQueryByCourse(AccompanyingPeriod $course): QueryBuilder + { + $qb = $this->repository->createQueryBuilder('d'); + + $qb + ->where($qb->expr()->eq('d.course', ':course')) + ->setParameter('course', $course); + + return $qb; + } + + public function countByCourse(AccompanyingPeriod $course): int + { + $qb = $this->buildQueryByCourse($course)->select('COUNT(d)'); + + return $qb->getQuery()->getSingleScalarResult(); + } + + public function find($id): ?AccompanyingCourseDocument + { + return $this->repository->find($id); + } + + public function findAll(): array + { + return $this->repository->findAll(); + } + + public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null) + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + public function findOneBy(array $criteria): ?AccompanyingCourseDocument + { + return $this->findOneBy($criteria); + } + + public function getClassName() + { + return AccompanyingCourseDocument::class; + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php new file mode 100644 index 000000000..0f85a74b2 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php @@ -0,0 +1,90 @@ +em = $em; + $this->authorizationHelper = $authorizationHelper; + $this->centerResolverDispatcher = $centerResolverDispatcher; + $this->security = $security; + } + + public function buildQueryByPerson(Person $person): QueryBuilder + { + $qb = $this->em->getRepository(PersonDocument::class)->createQueryBuilder('d'); + + $qb + ->where($qb->expr()->eq('d.person', ':person')) + ->setParameter('person', $person); + + return $qb; + } + + public function countByPerson(Person $person): int + { + $qb = $this->buildQueryByPerson($person)->select('COUNT(d)'); + + $this->addACL($qb, $person); + + return $qb->getQuery()->getSingleScalarResult(); + } + + public function findByPerson(Person $person, array $orderBy = [], int $limit = 20, int $offset = 0): array + { + $qb = $this->buildQueryByPerson($person)->select('d'); + + $this->addACL($qb, $person); + + foreach ($orderBy as [$field, $order]) { + $qb->addOrderBy($field, $order); + } + + $qb->setFirstResult($offset)->setMaxResults($limit); + + return $qb->getQuery()->getResult(); + } + + private function addACL(QueryBuilder $qb, Person $person): void + { + $center = $this->centerResolverDispatcher->resolveCenter($person); + + $reachableScopes = $this->authorizationHelper + ->getReachableScopes( + $this->security->getUser(), + PersonDocumentVoter::SEE, + $center + ); + + $qb->andWhere($qb->expr()->in('d.scope', ':scopes')) + ->setParameter('scopes', $reachableScopes); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php new file mode 100644 index 000000000..85b0288c0 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepositoryInterface.php @@ -0,0 +1,21 @@ +
@@ -9,8 +10,10 @@

{{ document.title }}

+ {{ mm.mimeIcon(document.object.type) }} + {% if document.description is not empty %} -
+
{{ document.description }}
{% endif %} @@ -42,26 +45,14 @@ {{ m.download_button(document.object, document.title) }}
  • - {% if not freezed %} - {% set button = { - 'changeIcon': 'fa-unlock', - } %}{# - 'changeClass' string - 'noText' boolean - #} - {# vue component - #} - {{ 'Edit'|trans }} - {% else %} - - {{ 'Update document'|trans }} - + {% if chill_document_is_editable(document.object) %} + {% if not freezed %} + {{ document.object|chill_document_edit_button({'title': document.title|e('html') }) }} + {% else %} + + {{ 'Update document'|trans }} + + {% endif %} {% endif %} {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_SEE', document) and document.course != null %}
  • diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig index e28611701..d7a5325cf 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/edit.html.twig @@ -19,7 +19,7 @@ {{ form_row(form.description) }} {{ form_row(form.object, { 'label': 'Document', 'existing': document.object }) }} -
  • {% endblock %} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig index 610b5249b..1e4fdb8e6 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/show.html.twig @@ -3,6 +3,7 @@ {% set activeRouteKey = '' %} {% import "@ChillDocStore/Macro/macro.html.twig" as m %} +{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %} {% block title %} {# {{ 'Detail of document of %name%'|trans({ '%name%': accompanyingCourse|chill_entity_render_string } ) }} #} @@ -18,16 +19,18 @@ {% block content %}

    {{ block('title') }}

    - -
    + + {{ mm.mimeIcon(document.object.type) }} + +
    {{ 'Title'|trans }}
    {{ document.title }}
    - + {% if document.category is not null %}
    {{ 'Category'|trans }}
    {{ document.category.name|localize_translatable_string }}
    {% endif %} - +
    {{ 'Description' | trans }}
    {% if document.description is empty %} @@ -39,7 +42,7 @@ {% endif %}
    - +
    {% endblock %} - + {% block block_post_menu %}
    {% endblock %} @@ -74,4 +81,4 @@ {{ parent() }} {{ encore_entry_script_tags('mod_async_upload') }} {{ encore_entry_script_tags('mod_entity_workflow_pick') }} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/Button/wopi_edit_document.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/Button/wopi_edit_document.html.twig new file mode 100644 index 000000000..f25c06030 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/Button/wopi_edit_document.html.twig @@ -0,0 +1,9 @@ + +{# Twig way + TODO: une route, un template avec un header CHILL et un iframe +#} + + {{ 'online_edit_document'|trans }} + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/List/list_item.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/List/list_item.html.twig new file mode 100644 index 000000000..358127bfb --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/List/list_item.html.twig @@ -0,0 +1,83 @@ +{% import "@ChillDocStore/Macro/macro.html.twig" as m %} +{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %} +
    +
    +
    +
    + {{ document.title }} +
    +
    + {{ mm.mimeIcon(document.object.type) }} +
    +
    +

    {{ document.category.name|localize_translatable_string }}

    +
    + {% if document.template is not null %} +
    +

    {{ document.template.name.fr }}

    +
    + {% endif %} +
    + +
    +
    + {% if document.date is not null %} +
    + {{ document.createdAt|format_date('short') }} +
    + {% endif %} +
    +
    +
    + {% if document.description is not empty %} +
    +
    + {{ document.description|chill_markdown_to_html }} +
    +
    + {% endif %} +
    +
    +
    + {{ 'Created by'|trans }}: + {{ document.createdBy|chill_entity_render_string }} + le {{ document.createdAt|format_date('long') }} +
    +
    +
    +
    + {% if document.course is defined %} +
      + {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_SEE_DETAILS', document) %} +
    • + {{ m.download_button(document.object, document.title) }} +
    • +
    • + +
    • + {% endif %} + {% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE', document) %} +
    • + +
    • + {% endif %} +
    + {% else %} +
      + {% if is_granted('CHILL_PERSON_DOCUMENT_SEE_DETAILS', document) %} +
    • + {{ m.download_button(document.object, document.title) }} +
    • +
    • + +
    • + {% endif %} + {% if is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document) %} +
    • + +
    • + {% endif %} +
    + {% endif %} +
    +
    diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/Macro/macro_mimeicon.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/Macro/macro_mimeicon.html.twig new file mode 100644 index 000000000..a9bc07e2f --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/Macro/macro_mimeicon.html.twig @@ -0,0 +1,55 @@ +{% macro mimeIcon(type) %} + + {# mapping + forkawesome and mime type https://gist.github.com/colemanw/9c9a12aae16a4bfe2678de86b661d922 + #} + {% set mapmime = { + 'image': 'fa-file-image-o', + 'audio': 'fa-file-audio-o', + 'video': 'fa-file-video-o', + 'application/pdf': 'fa-file-pdf-o', + 'application/msword': 'fa-file-word-o', + 'application/vnd.ms-word': 'fa-file-word-o', + 'application/vnd.oasis.opendocument.text': 'fa-file-word-o', + 'application/vnd.openxmlformats-officedocument.wordprocessingml': 'fa-file-word-o', + 'application/vnd.ms-excel': 'fa-file-excel-o', + 'application/vnd.openxmlformats-officedocument.spreadsheetml': 'fa-file-excel-o', + 'application/vnd.oasis.opendocument.spreadsheet': 'fa-file-excel-o', + 'application/vnd.ms-powerpoint': 'fa-file-powerpoint-o', + 'application/vnd.openxmlformats-officedocument.presentationml': 'fa-file-powerpoint-o', + 'application/vnd.oasis.opendocument.presentation': 'fa-file-powerpoint-o', + 'text/plain': 'fa-file-text-o', + 'text/html': 'fa-file-code-o', + 'application/json': 'fa-file-code-o', + 'application/gzip': 'fa-file-archive-o', + 'application/zip': 'fa-file-archive-o', + } %} + + {% set icon = 'fa-file-o' %} + {% for key,val in mapmime %} + {% if type starts with key %} + {% set icon = val %} + {% endif %} + {% endfor %} + + {# TODO improve mapping + mime type and friendly name https://gist.github.com/rosskmurphy/3724501 + #} + {% set maptype = { + 'fa-file-word-o': 'office document/texte', + 'fa-file-excel-o': 'office document/tableur', + 'fa-file-powerpoint-o': 'office document/presentation', + } %} + + {% set label = type %} + {% for key, val in maptype %} + {% if icon == key %} + {% set label = val %} + {% endif %} + {% endfor %} + +
    + + {{ label|capitalize }} +
    +{% endmacro %} \ No newline at end of file diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/edit.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/edit.html.twig index bf3dcd407..7533f1120 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/edit.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/edit.html.twig @@ -30,7 +30,9 @@ {{ form_row(form.title) }} {{ form_row(form.date) }} {{ form_row(form.category) }} - {{ form_row(form.scope) }} + {% if form.scope is defined %} + {{ form_row(form.scope) }} + {% endif %} {{ form_row(form.description) }} {{ form_row(form.object, { 'label': 'Document', 'existing': document.object }) }} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/index.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/index.html.twig index 40c85002e..b3d2baab6 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/index.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/index.html.twig @@ -30,54 +30,24 @@ {% endblock %} {% block personcontent %} + +

    {{ 'Documents for %name%'|trans({ '%name%': person|chill_entity_render_string } ) }}

    - - - - - - - - - - - + {% if documents|length == 0 %} +

    {{ 'No documents'|trans }}

    + {% else %} +
    {% for document in documents %} -
    - - - - - - {% else %} - - - + {% include 'ChillDocStoreBundle:List:list_item.html.twig' %} {% endfor %} - -
    {{ 'Title' | trans }}{{ 'Category'|trans }}{{ 'Circle' | trans }}{{ 'Actions' | trans }}
    {{ document.title }}{{ document.category.name|localize_translatable_string }}{{ document.scope.name|localize_translatable_string }} -
      - {% if is_granted('CHILL_PERSON_DOCUMENT_SEE_DETAILS', document) %} -
    • - {{ m.download_button(document.object, document.title) }} -
    • -
    • - -
    • - {% endif %} - {% if is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document) %} -
    • - -
    • - {% endif %} -
    -
    - {{ 'Any document found'|trans }} -
    +
    + {% endif %} + + {{ chill_pagination(pagination) }} {% if is_granted('CHILL_PERSON_DOCUMENT_CREATE', person) %} -
    {% endblock %} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/show.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/show.html.twig index f22864645..723757425 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/show.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/PersonDocument/show.html.twig @@ -19,6 +19,7 @@ {% set activeRouteKey = '' %} {% import "@ChillDocStore/Macro/macro.html.twig" as m %} +{% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %} {% block title %}{{ 'Detail of document of %name%'|trans({ '%name%': person|chill_entity_render_string } ) }}{% endblock %} @@ -29,12 +30,16 @@ {% block personcontent %}

    {{ 'Document %title%' | trans({ '%title%': document.title }) }}

    + {{ mm.mimeIcon(document.object.type) }} +
    {{ 'Title'|trans }}
    {{ document.title }}
    + {% if document.scope is not null %}
    {{ 'Scope' | trans }}
    {{ document.scope.name | localize_translatable_string }}
    + {% endif %}
    {{ 'Category'|trans }}
    {{ document.category.name|localize_translatable_string }}
    @@ -52,7 +57,7 @@
    -