From 43791badd51e16a41b99ecf6ac3204fa11b5c3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 8 Nov 2022 19:24:22 +0100 Subject: [PATCH] Feature: [saved export] Edit and delete saved exports --- .../Controller/ExportController.php | 6 +- .../Controller/SavedExportController.php | 97 ++++++++++++++++++- .../views/SavedExport/delete.html.twig | 25 +++++ .../views/SavedExport/edit.html.twig | 21 ++++ .../views/SavedExport/index.html.twig | 12 ++- .../Authorization/SavedExportVoter.php | 15 ++- .../translations/messages.fr.yml | 6 ++ 7 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/views/SavedExport/delete.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/SavedExport/edit.html.twig diff --git a/src/Bundle/ChillMainBundle/Controller/ExportController.php b/src/Bundle/ChillMainBundle/Controller/ExportController.php index 293a3c778..84bf80c6b 100644 --- a/src/Bundle/ChillMainBundle/Controller/ExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/ExportController.php @@ -170,7 +170,11 @@ class ExportController extends AbstractController return $this->redirectToRoute( 'chill_main_export_download', - ['alias' => $savedExport->getExportAlias(), 'key' => $key, 'prevent_save' => true] + [ + 'alias' => $savedExport->getExportAlias(), + 'key' => $key, 'prevent_save' => true, + 'returnPath' => $this->generateUrl('chill_main_export_saved_list_my'), + ] ); } diff --git a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php index 051fa5231..197fe253d 100644 --- a/src/Bundle/ChillMainBundle/Controller/SavedExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/SavedExportController.php @@ -16,38 +16,132 @@ use Chill\MainBundle\Entity\User; use Chill\MainBundle\Export\ExportInterface; use Chill\MainBundle\Export\ExportManager; use Chill\MainBundle\Export\GroupedExportInterface; +use Chill\MainBundle\Form\SavedExportType; use Chill\MainBundle\Repository\SavedExportRepositoryInterface; +use Chill\MainBundle\Security\Authorization\SavedExportVoter; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Security; use Symfony\Component\Templating\EngineInterface; use Symfony\Contracts\Translation\TranslatorInterface; +use function count; class SavedExportController { + private EntityManagerInterface $entityManager; + private ExportManager $exportManager; + private FormFactoryInterface $formFactory; + private SavedExportRepositoryInterface $savedExportRepository; private Security $security; + private SessionInterface $session; + private EngineInterface $templating; private TranslatorInterface $translator; + private UrlGeneratorInterface $urlGenerator; + public function __construct( EngineInterface $templating, + EntityManagerInterface $entityManager, ExportManager $exportManager, + FormFactoryInterface $formBuilder, SavedExportRepositoryInterface $savedExportRepository, Security $security, - TranslatorInterface $translator + SessionInterface $session, + TranslatorInterface $translator, + UrlGeneratorInterface $urlGenerator ) { $this->exportManager = $exportManager; + $this->entityManager = $entityManager; + $this->formFactory = $formBuilder; $this->savedExportRepository = $savedExportRepository; $this->security = $security; + $this->session = $session; $this->templating = $templating; $this->translator = $translator; + $this->urlGenerator = $urlGenerator; + } + + /** + * @Route("/{_locale}/exports/saved/{id}/delete", name="chill_main_export_saved_delete") + */ + public function delete(SavedExport $savedExport, Request $request): Response + { + if (!$this->security->isGranted(SavedExportVoter::DELETE, $savedExport)) { + throw new AccessDeniedHttpException(); + } + + $form = $this->formFactory->create(); + $form->add('submit', SubmitType::class, ['label' => 'Delete']); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->entityManager->remove($savedExport); + $this->entityManager->flush(); + + $this->session->getFlashBag()->add('success', $this->translator->trans('saved_export.Export is deleted')); + + return new RedirectResponse( + $this->urlGenerator->generate('chill_main_export_saved_list_my') + ); + } + + return new Response( + $this->templating->render( + '@ChillMain/SavedExport/delete.html.twig', + [ + 'saved_export' => $savedExport, + 'delete_form' => $form->createView(), + ] + ) + ); + } + + /** + * @Route("/{_locale}/exports/saved/{id}/edit", name="chill_main_export_saved_edit") + */ + public function edit(SavedExport $savedExport, Request $request): Response + { + if (!$this->security->isGranted(SavedExportVoter::EDIT, $savedExport)) { + throw new AccessDeniedHttpException(); + } + + $form = $this->formFactory->create(SavedExportType::class, $savedExport); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $this->entityManager->flush(); + + $this->session->getFlashBag()->add('success', $this->translator->trans('saved_export.Saved export is saved!')); + + return new RedirectResponse( + $this->urlGenerator->generate('chill_main_export_saved_list_my') + ); + } + + return new Response( + $this->templating->render( + '@ChillMain/SavedExport/edit.html.twig', + [ + 'form' => $form->createView(), + ] + ) + ); } /** @@ -83,6 +177,7 @@ class SavedExportController '@ChillMain/SavedExport/index.html.twig', [ 'grouped_exports' => $exportsGrouped, + 'total' => count($exports), ] ) ); diff --git a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/delete.html.twig b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/delete.html.twig new file mode 100644 index 000000000..5d90699df --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/delete.html.twig @@ -0,0 +1,25 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title 'saved_export.Delete saved ?'|trans %} + +{% block display_content %} +
+

{{ saved_export.title }}

+

{{ saved_export.description|chill_markdown_to_html }}

+ +
+{% endblock %} + +{% block content %} +
+ {{ include('@ChillMain/Util/confirmation_template.html.twig', + { + 'title' : 'saved_export.Delete saved ?'|trans, + 'confirm_question' : 'saved_export.Are you sure you want to delete this saved ?'|trans, + 'display_content' : block('display_content'), + 'cancel_route' : 'chill_main_export_saved_list_my', + 'cancel_parameters' : {}, + 'form' : delete_form + } ) }} +
+{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/edit.html.twig b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/edit.html.twig new file mode 100644 index 000000000..937d42201 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/edit.html.twig @@ -0,0 +1,21 @@ +{% extends "@ChillMain/layout.html.twig" %} + +{% block title %}{{ 'saved_export.Edit'|trans }}{% endblock %} + +{% block content %} +

{{ block('title') }}

+ + {{ form_start(form) }} + {{ form_row(form.title) }} + {{ form_row(form.description) }} + + + {{ form_end(form) }} +{% endblock %} \ No newline at end of file diff --git a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig index 5cd697bb4..bfe377f6c 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/SavedExport/index.html.twig @@ -8,6 +8,10 @@
+ {% if total == 0 %} +

{{ 'saved_export.Any saved export'|trans }}

+ {% endif %} + {% for group, saveds in grouped_exports %} {% if group != '_' %}

{{ group }}

@@ -21,8 +25,8 @@
@@ -47,8 +51,8 @@ diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php b/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php index bc74e2d45..667bced46 100644 --- a/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php +++ b/src/Bundle/ChillMainBundle/Security/Authorization/SavedExportVoter.php @@ -15,20 +15,33 @@ use Chill\MainBundle\Entity\SavedExport; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; use UnexpectedValueException; +use function in_array; class SavedExportVoter extends Voter { + public const DELETE = 'CHLL_MAIN_EXPORT_SAVED_DELETE'; + + public const EDIT = 'CHLL_MAIN_EXPORT_SAVED_EDIT'; + public const GENERATE = 'CHLL_MAIN_EXPORT_SAVED_GENERATE'; + private const ALL = [ + self::DELETE, + self::EDIT, + self::GENERATE, + ]; + protected function supports($attribute, $subject): bool { - return $subject instanceof SavedExport && self::GENERATE === $attribute; + return $subject instanceof SavedExport && in_array($attribute, self::ALL, true); } protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool { /** @var SavedExport $subject */ switch ($attribute) { + case self::DELETE: + case self::EDIT: case self::GENERATE: return $subject->getUser() === $token->getUser(); diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 498f185b6..1100d8ee3 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -558,5 +558,11 @@ rolling_date: fixed_date_date: Date fixe saved_export: + Any saved export: Aucun rapport enregistré New: Nouveau rapport enregistré + Edit: Modifier un rapport enregistré + Delete saved ?: Supprimer un rapport enregistré ? + Are you sure you want to delete this saved ?: Êtes-vous sûr·e de vouloir supprimer ce rapport ? My saved exports: Mes rapports enregistrés + Export is deleted: Le rapport est supprimé + Saved export is saved!: Le rapport est enregistré \ No newline at end of file