From fb65bcadfd4c628de65282da515dd360d006b1ea Mon Sep 17 00:00:00 2001
From: Camille Simiand <camille.simiand@tetras-libre.fr>
Date: Mon, 21 Feb 2022 12:07:02 +0100
Subject: [PATCH] Have a better UI - Split group creation

---
 assets/styles/app.scss                        |   5 +-
 src/Controller/CapsuleGroupController.php     | 139 ++++++++++++------
 src/Form/DeleteGroupFormType.php              |  37 +++++
 ...dit.html.twig => capsule_groups.html.twig} |  18 +--
 templates/capsule/groups/create.html.twig     |   2 +-
 templates/capsule/groups/delete.html.twig     |  34 +++++
 .../capsule/groups/user_groups.html.twig      |  66 +++++++++
 templates/layout.html.twig                    |   9 +-
 .../functional/CapsuleGroupControllerTest.php |  17 +--
 translations/messages.en.yaml                 |  10 +-
 translations/messages.fr.yaml                 |   8 +
 11 files changed, 270 insertions(+), 75 deletions(-)
 create mode 100644 src/Form/DeleteGroupFormType.php
 rename templates/capsule/groups/{edit.html.twig => capsule_groups.html.twig} (78%)
 create mode 100644 templates/capsule/groups/delete.html.twig
 create mode 100644 templates/capsule/groups/user_groups.html.twig

diff --git a/assets/styles/app.scss b/assets/styles/app.scss
index cf68905..764d94d 100644
--- a/assets/styles/app.scss
+++ b/assets/styles/app.scss
@@ -95,16 +95,15 @@ button[type=submit]{
 
 .standard-button {
   line-height: 40px;
-  margin: 30px 0 0 0;
   padding: 0.5em 2em;
-  font-size: 14px;
-  text-transform: uppercase;
+  font-size: 16px;
   font-weight: bold;
   border: none;
   color: #FFF !important;
   border-radius: 3px;
   background: #49AD9A;
   box-shadow: 0 -2px 0 #3B8C7E inset;
+  flex-basis: auto;
 }
 
 .standard-button:hover {
diff --git a/src/Controller/CapsuleGroupController.php b/src/Controller/CapsuleGroupController.php
index d488c5d..6c672ae 100755
--- a/src/Controller/CapsuleGroupController.php
+++ b/src/Controller/CapsuleGroupController.php
@@ -6,6 +6,7 @@ use App\Entity\Capsule;
 use App\Entity\Group;
 use App\Entity\User;
 use App\Form\CreateCapsuleGroupsFormType;
+use App\Form\DeleteGroupFormType;
 use App\Form\RemoveGroupFormType;
 use App\Form\SelectCapsuleGroupsFormType;
 use App\Repository\CapsuleRepository;
@@ -38,9 +39,9 @@ class CapsuleGroupController extends AbstractController
     }
 
     /**
-     * @Route("/capsule/{capsule_id}/groups/edit", name="edit_capsule_groups")
+     * @Route("/my_groups", name="edit_user_groups")
      */
-    public function edit(int $capsule_id, Request $request): Response
+    public function editUserGroups(): Response
     {
         $current_user = $this->getUser();
 
@@ -48,58 +49,105 @@ class CapsuleGroupController extends AbstractController
             return $this->redirectToRoute('app_logout');
         }
 
-        $capsule = $this->capsule_repository->findOneBy(['id' => $capsule_id]);
+        $groups = $current_user->getGroups()->toArray();
 
-        if (! $capsule instanceof Capsule) {
-            throw new \Exception("Capsule does not exist");
+        return $this->render('capsule/groups/user_groups.html.twig', [
+            'groups' => $groups
+        ]);
+    }
+
+    /**
+     * @Route("my_groups/create", name="create_group")
+     */
+    public function create(Request $request): Response
+    {
+        $current_user = $this->getUser();
+
+        if (! $current_user instanceof User) {
+            return $this->redirectToRoute('app_logout');
         }
 
-        $capsule_groups_by_author = $current_user->getGroupsByCapsule($capsule);
-        $author_capsule_groups_not_added = $capsule->getNotAddedGroupsByAuthor($current_user);
+        $group = new Group();
+        $group->setAuthor($current_user);
 
-        $form = $this->createForm(
-            SelectCapsuleGroupsFormType::class,
-            ['groups' => $author_capsule_groups_not_added]
-        );
+        $form = $this->createForm(CreateCapsuleGroupsFormType::class, $group);
         $form->handleRequest($request);
 
         if ($form->isSubmitted() && $form->isValid()) {
-            $capsule_groups = $this->addGroups($form, $capsule);
+            $group = $this->createAGroup($form, $group);
 
-            $groups_names = [];
+            $this->addFlash(
+                'success',
+                $this->translator->trans(
+                    'groups.create.success',
+                    [
+                        'group_name' => $group->getName()
+                    ]
+                )
+            );
 
-            foreach ($capsule_groups as $group) {
-                $groups_names[] = $group->getName();
+            return $this->redirectToRoute('edit_user_groups');
+        }
+
+        return $this->render('capsule/groups/create.html.twig', [
+            'createCapsuleGroupsForm' => $form->createView()
+        ]);
+    }
+
+    /**
+     * @Route("/my_groups/{group_id}/delete", name="delete_group")
+     */
+    public function deleteGroup(int $group_id, Request $request): Response
+    {
+        $current_user = $this->getUser();
+        if (! $current_user instanceof User) {
+            return $this->redirectToRoute('app_logout');
+        }
+
+        $group = $this->group_repository->findOneBy(['id' => $group_id]);
+        if (! $group instanceof Group) {
+            throw new \Exception('Group not found');
+        }
+
+        $form = $this->createForm(DeleteGroupFormType::class);
+        $form->handleRequest($request);
+
+        if ($form->isSubmitted() && $form->isValid()) {
+            $capsules = $group->getCapsules()->toArray();
+            foreach ($capsules as $capsule) {
+                $capsule->removeGroup($group);
+                $this->entity_manager->persist($capsule);
             }
 
+            $current_user->removeGroup($group);
+            $this->entity_manager->persist($current_user);
+
+            $this->entity_manager->remove($group);
+            $this->entity_manager->flush();
+
             $this->addFlash(
                 'success',
                 $this->translator->trans(
-                    'groups.add.success',
+                    'groups.general.delete.success',
                     [
-                        'groups_names' => implode(",", $groups_names),
-                        'capsule_name' => $capsule->getName()
+                        'group_name' => $group->getName()
                     ]
                 )
             );
 
-            return $this->redirectToRoute('edit_capsule_groups', [
-                'capsule_id' => $capsule_id
-            ]);
+            return $this->redirectToRoute('edit_user_groups');
         }
 
-        return $this->render('capsule/groups/edit.html.twig', [
-            'selectCapsuleGroupsForm' => $form->createView(),
-            'capsule' => $capsule,
-            'groups' => $capsule_groups_by_author,
-            'groups_not_added' => $author_capsule_groups_not_added
+        return $this->render('capsule/groups/delete.html.twig', [
+            'deleteGroupForm' => $form->createView(),
+            'group_name' => $group->getName()
         ]);
     }
 
     /**
-     * @Route("capsule/{capsule_id}/groups/create", name="create_group")
+     * @Route("/capsule/{capsule_id}/groups/edit", name="edit_capsule_groups")
      */
-    public function create(int $capsule_id, Request $request): Response
+    public function edit(int $capsule_id, Request $request): Response
     {
         $current_user = $this->getUser();
 
@@ -113,21 +161,31 @@ class CapsuleGroupController extends AbstractController
             throw new \Exception("Capsule does not exist");
         }
 
-        $group = new Group();
-        $group->setAuthor($current_user);
+        $capsule_groups_by_author = $current_user->getGroupsByCapsule($capsule);
+        $author_capsule_groups_not_added = $capsule->getNotAddedGroupsByAuthor($current_user);
 
-        $form = $this->createForm(CreateCapsuleGroupsFormType::class, $group);
+        $form = $this->createForm(
+            SelectCapsuleGroupsFormType::class,
+            ['groups' => $author_capsule_groups_not_added]
+        );
         $form->handleRequest($request);
 
         if ($form->isSubmitted() && $form->isValid()) {
-            $group = $this->createAGroup($form, $capsule, $group);
+            $capsule_groups = $this->addGroups($form, $capsule);
+
+            $groups_names = [];
+
+            foreach ($capsule_groups as $group) {
+                $groups_names[] = $group->getName();
+            }
 
             $this->addFlash(
                 'success',
                 $this->translator->trans(
-                    'groups.create.success',
+                    'groups.add.success',
                     [
-                        'group_name' => $group->getName()
+                        'groups_names' => implode(",", $groups_names),
+                        'capsule_name' => $capsule->getName()
                     ]
                 )
             );
@@ -137,9 +195,11 @@ class CapsuleGroupController extends AbstractController
             ]);
         }
 
-        return $this->render('capsule/groups/create.html.twig', [
-            'createCapsuleGroupsForm' => $form->createView(),
-            'capsule' => $capsule
+        return $this->render('capsule/groups/capsule_groups.html.twig', [
+            'selectCapsuleGroupsForm' => $form->createView(),
+            'capsule' => $capsule,
+            'groups' => $capsule_groups_by_author,
+            'groups_not_added' => $author_capsule_groups_not_added
         ]);
     }
 
@@ -228,16 +288,11 @@ class CapsuleGroupController extends AbstractController
 
     private function createAGroup(
         FormInterface $form,
-        Capsule $capsule,
         Group $group
     ): Group {
         $group_name = $form->get('name')->getData();
         $group->setName($group_name);
         $this->entity_manager->persist($group);
-
-        $capsule->addGroup($group);
-        $this->entity_manager->persist($capsule);
-
         $this->entity_manager->flush();
 
         return $group;
diff --git a/src/Form/DeleteGroupFormType.php b/src/Form/DeleteGroupFormType.php
new file mode 100644
index 0000000..20b0ef3
--- /dev/null
+++ b/src/Form/DeleteGroupFormType.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Form;
+
+use App\Entity\Group;
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\ButtonType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class DeleteGroupFormType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options): void
+    {
+        $builder
+            ->add(
+                'cancel',
+                ButtonType::class,
+                ['label' => 'general.cancel_button',
+                    'attr' => ['class' => 'button-cancel']
+                ]
+            )
+            ->add(
+                'delete',
+                SubmitType::class,
+                ['label' => 'general.delete']
+            );
+    }
+
+    public function configureOptions(OptionsResolver $resolver): void
+    {
+        $resolver->setDefaults([
+            'data_class' => Group::class,
+        ]);
+    }
+}
diff --git a/templates/capsule/groups/edit.html.twig b/templates/capsule/groups/capsule_groups.html.twig
similarity index 78%
rename from templates/capsule/groups/edit.html.twig
rename to templates/capsule/groups/capsule_groups.html.twig
index fc833d2..5129485 100644
--- a/templates/capsule/groups/edit.html.twig
+++ b/templates/capsule/groups/capsule_groups.html.twig
@@ -39,12 +39,14 @@
                     <ul class="ps-0">
                         {% for group in groups %}
                             {% if group.getName() != 'groups.filter.no_filter'|trans %}
-                                <li class="text-capitalize text-secondary list-unstyled p-1">
-                                    {{ group.getName() }}
+                                <li class="text-secondary list-unstyled p-1">
+                                    <span class="text-capitalize">
+                                        {{ group.getName() }}
+                                    </span>
                                         -
-                                        <a href="/capsule/{{ capsule.getId() }}/groups/{{ group.getId() }}/remove" class="remove-link">
-                                            {{ 'groups.remove.link'|trans }}
-                                        </a>
+                                    <a href="/capsule/{{ capsule.getId() }}/groups/{{ group.getId() }}/remove" class="remove-link">
+                                        {{ 'groups.remove.link'|trans }}
+                                    </a>
                                 </li>
                             {% endif %}
                         {% endfor %}
@@ -53,12 +55,6 @@
             </div>
 
             <div class="d-flex flex-column justify-content-center order-md-2 mb-4 col-sm-8 col-md-6 col-lg-5 col-xl-4">
-                <h5 class="mb-5">
-                    <a href="/capsule/{{ capsule.getId() }}/groups/create" class="list-unstyled">
-                        {{ 'groups.create.title'|trans }}
-                    </a>
-                </h5>
-
                 {% if groups_not_added is not empty %}
                     <div class="d-flex flex-column justify-content-center mb-4">
                         {{ form_start(selectCapsuleGroupsForm, {'attr': {novalidate: 'novalidate'}}) }}
diff --git a/templates/capsule/groups/create.html.twig b/templates/capsule/groups/create.html.twig
index c590d3a..aa0da53 100644
--- a/templates/capsule/groups/create.html.twig
+++ b/templates/capsule/groups/create.html.twig
@@ -23,7 +23,7 @@
 
             <div class="d-flex flex-column flex-sm-row justify-content-center align-items-center align-items-sm-start">
                 {{ form_row(createCapsuleGroupsForm.validate, {'row_attr': {'class' : 'me-sm-3 mb-3'}}) }}
-                <a href="/capsule/{{ capsule.getId() }}/groups/edit">
+                <a href="/my_groups">
                     {{ form_row(createCapsuleGroupsForm.go_back) }}
                 </a>
             </div>
diff --git a/templates/capsule/groups/delete.html.twig b/templates/capsule/groups/delete.html.twig
new file mode 100644
index 0000000..80dcb3e
--- /dev/null
+++ b/templates/capsule/groups/delete.html.twig
@@ -0,0 +1,34 @@
+{% extends 'layout.html.twig' %}
+
+{% block title %}
+    {{ 'groups.general.delete.title'|trans }}
+{% endblock %}
+
+{% block body %}
+
+    <div>
+        <div class="row w-100 gx-0">
+            <div class="row-title-box">
+                <h3 class="row-title">
+                    {{ 'groups.general.delete.title'|trans }}
+                </h3>
+            </div>
+        </div>
+
+        <div class="d-flex flex-column justify-content-center align-items-center">
+
+            <p class="text-secondary fs-5 mb-5">
+                {{ 'groups.general.delete.text'|trans({'%group_name%': group_name}) }}
+            </p>
+
+            {{ form_start(deleteGroupForm, {'attr': {novalidate: 'novalidate', 'class': 'd-flex flex-row justify-content-center'}}) }}
+            {{ form_row(deleteGroupForm.delete, {'row_attr': {'class' : 'm-auto mb-2 me-3'}})  }}
+            <a href="/my_groups">
+                {{ form_row(deleteGroupForm.cancel, {'row_attr': {'class' : 'm-auto mb-2 bg-secondary rounded ms-3'}})  }}
+            </a>
+            {{ form_end(deleteGroupForm) }}
+        </div>
+
+    </div>
+
+{%  endblock %}
\ No newline at end of file
diff --git a/templates/capsule/groups/user_groups.html.twig b/templates/capsule/groups/user_groups.html.twig
new file mode 100644
index 0000000..db6848f
--- /dev/null
+++ b/templates/capsule/groups/user_groups.html.twig
@@ -0,0 +1,66 @@
+{% extends 'layout.html.twig' %}
+
+{% block title %}
+    {{ 'groups.general.title'|trans }}
+    -
+    {{ parent() }}
+{% endblock %}
+
+{% block body %}
+    <div>
+        <div class="row w-100 gx-0">
+            <div class="row-title-box">
+                <h3 class="row-title">
+                    {{ 'groups.general.title'|trans }}
+                </h3>
+            </div>
+        </div>
+
+        {% for flashWarning in app.flashes('warning') %}
+            <div class="text-center alert alert-warning col-5 mx-auto my-5 mt-2" role="alert">
+                {{ flashWarning }}
+            </div>
+        {% endfor %}
+
+        {% for flashSuccess in app.flashes('success') %}
+            <div class="text-center alert alert-success col-5 mx-auto my-5 mt-2" role="alert">
+                {{ flashSuccess }}
+            </div>
+        {% endfor %}
+
+        <div class="d-flex flex-md-row flex-column justify-content-center">
+
+            <div class="d-flex flex-row pe-md-5 fw-normal me-0 me-md-5">
+                <div class="pe-3 pe-md-4 text-nowrap">
+                    <h5>
+                        {{ 'groups.general.all'|trans }}
+                    </h5>
+                    <ul class="ps-0">
+                        {% for group in groups %}
+                            {% if group.getName() != 'groups.filter.no_filter'|trans %}
+                                <li class="text-secondary list-unstyled p-1">
+                                    <span class="text-capitalize">
+                                        {{ group.getName() }}
+                                    </span>
+                                    -
+                                    <a href="/my_groups/{{ group.getId() }}/delete" class="remove-link">
+                                        {{ 'general.delete'|trans }}
+                                    </a>
+                                </li>
+                            {% endif %}
+                        {% endfor %}
+                    </ul>
+                </div>
+            </div>
+
+            <div class="d-flex align-items-center mt-3 mt-md-0">
+                <button type="submit" class="p-2">
+                    <a href="/my_groups/create" class="list-unstyled text-decoration-none text-white">
+                        {{ 'groups.create.title'|trans }}
+                    </a>
+                </button>
+            </div>
+
+        </div>
+    </div>
+{%  endblock %}
\ No newline at end of file
diff --git a/templates/layout.html.twig b/templates/layout.html.twig
index deb0ae7..a202620 100644
--- a/templates/layout.html.twig
+++ b/templates/layout.html.twig
@@ -25,9 +25,14 @@
   </a>
 
         {% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
-          <div id="user-block">
+          <div id="user-block" class="d-flex flex-column">
             <div id="user-block-nom">{{ app.user.firstName }} {{ app.user.lastName }}</div>
-            <a href="{{ path('show_profile') }}" class="text-decoration-none fs-5">My profile</a>
+            <a href="{{ path('show_profile') }}" class="text-decoration-none fs-5">
+              {{ 'user.profile.title'|trans }}
+            </a>
+            <a href="{{ path('edit_user_groups') }}" class="text-decoration-none fs-5">
+              {{ 'groups.general.title'|trans }}
+            </a>
             <form>
               <button class="btn btn-primary" formaction="/logout">
                 {{ 'general.log_out'|trans }}
diff --git a/tests/functional/CapsuleGroupControllerTest.php b/tests/functional/CapsuleGroupControllerTest.php
index 601fca5..ac32fb8 100644
--- a/tests/functional/CapsuleGroupControllerTest.php
+++ b/tests/functional/CapsuleGroupControllerTest.php
@@ -23,7 +23,6 @@ class CapsuleGroupControllerTest extends WebTestCase
     private User $user_2;
     private Group $group_pop_own_by_user_1;
     private Group $group_rock_own_by_user_1;
-    private Capsule $capsule;
 
     protected function setUp(): void
     {
@@ -40,7 +39,6 @@ class CapsuleGroupControllerTest extends WebTestCase
         $this->group_repository = $this->object_manager->getRepository(Group::class);
 
         $this->setUsers();
-        $this->setCapsule();
         $this->setCapsuleGroupPop();
         $this->setCapsuleGroupRock();
     }
@@ -54,7 +52,7 @@ class CapsuleGroupControllerTest extends WebTestCase
     public function testUserShouldNotBeAbleToCreateACapsuleGroupWithExistingGroupName(): void
     {
         $this->client->loginUser($this->user_1);
-        $uri = '/capsule/' . $this->capsule->getId() . '/groups/create';
+        $uri = '/my_groups/create';
         $crawler = $this->client->request('GET', $uri);
         $this->assertResponseIsSuccessful();
 
@@ -72,7 +70,7 @@ class CapsuleGroupControllerTest extends WebTestCase
     public function testUserShouldBeAbleToCreateACapsuleGroupWithTheSameGroupNameUsedByAnotherUser(): void
     {
         $this->client->loginUser($this->user_2);
-        $uri = '/capsule/' . $this->capsule->getId() . '/groups/create';
+        $uri = '/my_groups/create';
         $crawler = $this->client->request('GET', $uri);
         $this->assertResponseIsSuccessful();
 
@@ -108,17 +106,6 @@ class CapsuleGroupControllerTest extends WebTestCase
         $this->user_2 = $user_2;
     }
 
-    private function setCapsule(): void
-    {
-        $capsule = $this->capsule_repository->findOneBy(['name' => 'Pomme']);
-
-        if (! $capsule instanceof Capsule) {
-            throw new \Exception("Capsule does not exist.");
-        }
-
-        $this->capsule = $capsule;
-    }
-
     private function setCapsuleGroupPop(): void
     {
         $group_pop = $this->group_repository->findOneBy(['name' => 'Pop', 'author' => $this->user_1]);
diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml
index 0ca87ae..637a19c 100644
--- a/translations/messages.en.yaml
+++ b/translations/messages.en.yaml
@@ -9,6 +9,7 @@ general:
   greeting: Cheers!
   validate: Validate
   save: Save
+  delete: Delete
 
 login:
   account_disabled_feedback: Your user account is disabled. Please click on the link your receive by email to validate your registration.
@@ -159,6 +160,13 @@ editors:
           If you want to remove the capsule from your list, go to the capsule list page and click on "delete capsule"
 
 groups:
+  general:
+    title: My groups
+    all: All groups
+    delete:
+      title: Delete
+      text: Do you really want to delete group %group_name%?
+      success: Group group_name deleted successfully
   list:
     title: Capsule groups
   edit:
@@ -169,7 +177,7 @@ groups:
     success: Group group_name has been created and added to the capsule successfully
     name: Choose a new group name
     validate: Create a new group
-    go_back: Go back to capsule groups
+    go_back: Go back to my groups
   add:
     success: Group(s) groups_names has/have been added successfully to capsule capsule_name
     validate: Add theses groups to the capsule
diff --git a/translations/messages.fr.yaml b/translations/messages.fr.yaml
index 258d7ce..b4fef15 100644
--- a/translations/messages.fr.yaml
+++ b/translations/messages.fr.yaml
@@ -9,6 +9,7 @@ general:
   greeting: Salutation !
   validate: Valider
   save: Enregistrer
+  delete: Supprimer
 
 login:
   account_disabled_feedback: Le compte utilisateur a été désactivé. Veuillez cliquer sur le lien pour recevoir un courriel de validation
@@ -158,6 +159,13 @@ editors:
           Si vous voulez enlever la capsule de votre liste, allez sur la page qui affiche la liste de vos capsules et cliquer sur "supprimer la capsule"
 
 groups:
+  general:
+    title: Mes groupes
+    all: Tous les groupes
+    delete:
+      title: Supprimer le groupe
+      text: Souhaitez-vous vraiment supprimer le groupe %group_name% ?
+      success: Le groupe group_name a bien été supprimé
   list:
     title: Groupes de la capsule
   edit:
-- 
GitLab