]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
MOAR WIP
authorThomas Citharel <tcit@tcit.fr>
Thu, 27 Apr 2017 17:17:19 +0000 (19:17 +0200)
committerThomas Citharel <tcit@tcit.fr>
Fri, 23 Jun 2017 07:27:23 +0000 (09:27 +0200)
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
20 files changed:
src/Wallabag/CoreBundle/Controller/EntryController.php
src/Wallabag/CoreBundle/Controller/ExportController.php
src/Wallabag/CoreBundle/Entity/Entry.php
src/Wallabag/CoreBundle/Form/Type/EditGroupSharesType.php [new file with mode: 0644]
src/Wallabag/CoreBundle/Repository/EntryRepository.php
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_share_groups.html.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
src/Wallabag/GroupBundle/Controller/ManageController.php
src/Wallabag/GroupBundle/Form/UserGroupType.php
src/Wallabag/GroupBundle/Resources/config/services.yml
src/Wallabag/GroupBundle/Resources/views/Manage/edit_user.html.twig [new file with mode: 0644]
src/Wallabag/GroupBundle/Resources/views/Manage/index.html.twig
src/Wallabag/GroupBundle/Resources/views/Manage/manage.html.twig [new file with mode: 0644]
src/Wallabag/GroupBundle/Resources/views/Manage/requests.html.twig [new file with mode: 0644]
src/Wallabag/UserBundle/Entity/User.php
src/Wallabag/UserBundle/Repository/UserRepository.php
src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig

index fafa49f1b0bb69a156db8318a6ab3e9a9c2bba02..f1376f435e78db23091d80762166bb9fb36ed76c 100644 (file)
@@ -4,11 +4,15 @@ namespace Wallabag\CoreBundle\Controller;
 
 use Pagerfanta\Adapter\DoctrineORMAdapter;
 use Pagerfanta\Exception\OutOfRangeCurrentPageException;
+use Pagerfanta\Pagerfanta;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
 use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\CoreBundle\Form\Type\EditGroupSharesType;
 use Wallabag\CoreBundle\Form\Type\EntryFilterType;
 use Wallabag\CoreBundle\Form\Type\EditEntryType;
 use Wallabag\CoreBundle\Form\Type\NewEntryType;
@@ -16,6 +20,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
 use Wallabag\CoreBundle\Event\EntrySavedEvent;
 use Wallabag\CoreBundle\Event\EntryDeletedEvent;
 use Wallabag\CoreBundle\Form\Type\SearchEntryType;
+use Wallabag\GroupBundle\Entity\Group;
 
 class EntryController extends Controller
 {
@@ -604,4 +609,88 @@ class EntryController extends Controller
     {
         return $this->showEntries('untagged', $request, $page);
     }
+
+       /**
+        * @Route("/group-articles/{group}/{page}", name="group-presentations", defaults={"page" = "1"}, requirements={"page": "\d+", "group": "\d+"})
+        *
+        * @param Request $request
+        * @param Group $group
+        * @param int $page
+        * @return Response
+        */
+       public function showGroupSharedTemplatesAction(Request $request, Group $group, int $page)
+       {
+               if (!$this->getUser()->inGroup($group)) {
+                       throw $this->createAccessDeniedException();
+               }
+
+               $repository = $this->get('wallabag_core.entry_repository');
+
+               /** @var QueryBuilder $entries */
+               $entries = $repository->findByGroup($group->getId());
+
+               $pagerAdapter = new DoctrineORMAdapter($entries->getQuery(), true, false);
+               $pagerFanta = new Pagerfanta($pagerAdapter);
+               $pagerFanta->setMaxPerPage(9);
+
+               $form = $this->createForm(EntryFilterType::class);
+
+               if ($request->query->has($form->getName())) {
+                       // manually bind values from the request
+                       $form->submit($request->query->get($form->getName()));
+
+                       // build the query from the given form object
+                       $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $qb);
+               }
+
+               $searchTerm = (isset($request->get('search_entry')['term']) ? $request->get('search_entry')['term'] : '');
+
+               try {
+                       $pagerFanta->setCurrentPage($page);
+               } catch (OutOfRangeCurrentPageException $e) {
+                       if ($page > 1) {
+                               return $this->redirect($this->generateUrl('group-presentations', [
+                                       'page' => $pagerFanta->getNbPages(),
+                                       'group' => $group->getId()
+                               ]), 302);
+                       }
+               }
+
+               return $this->render('WallabagCoreBundle:Entry:entries.html.twig', [
+                       'form' => $form->createView(),
+                       'entries' => $pagerFanta,
+                       'currentPage' => $page,
+                       'searchTerm' => $searchTerm,
+               ]);
+       }
+
+    /**
+     *
+     * @Route("/entry/group-shares/{entry}", name="group-shares-entry")
+     *
+     * @param Request $request
+     * @param Entry $entry
+     * @return Response
+     */
+       public function groupShareAction(Request $request, Entry $entry)
+    {
+        $this->checkUserAction($entry);
+
+        $form = $this->createForm(EditGroupSharesType::class, $entry, ['groups' => $this->getUser()->getGroups()]);
+
+        $form->handleRequest($request);
+
+        if ($form->isSubmitted() && $form->isValid()) {
+            $em = $this->getDoctrine()->getManager();
+            $em->persist($entry);
+            $em->flush();
+
+            return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()]));
+        }
+
+        return $this->render('WallabagCoreBundle:Entry:_share_groups.html.twig', [
+            'form' => $form->createView(),
+            'entry' => $entry,
+        ]);
+    }
 }
index fda04cfbc82e7f9bf343868bd9a377a6bc0eea40..4bb2b706bb4f09d964c045ec719347bba0af81a5 100644 (file)
@@ -47,7 +47,7 @@ class ExportController extends Controller
      *
      * @Route("/export/{category}.{format}", name="export_entries", requirements={
      *     "format": "epub|mobi|pdf|json|xml|txt|csv",
-     *     "category": "all|unread|starred|archive|tag_entries|untagged|search"
+     *     "category": "all|unread|starred|archive|tag_entries|untagged|search|group-presentations"
      * })
      *
      * @return \Symfony\Component\HttpFoundation\Response
index 84555b3689800623e97a1b7dfff64c7ea0036276..028eeb52981d6b7085a1cc6746dc74dba59eee7c 100644 (file)
@@ -235,7 +235,7 @@ class Entry
 
     /**
      * @var ArrayCollection
-     * @ORM\ManyToMany(targetEntity="Wallabag\GroupBundle\Entity\Group", inversedBy="presentations", cascade={"persist"})
+     * @ORM\ManyToMany(targetEntity="Wallabag\GroupBundle\Entity\Group", inversedBy="entries", cascade={"persist"})
      */
     private $groupShares;
 
@@ -784,4 +784,20 @@ class Entry
 
         return $this;
     }
+
+    /**
+     * @return ArrayCollection
+     */
+    public function getGroupShares()
+    {
+        return $this->groupShares;
+    }
+
+    /**
+     * @param ArrayCollection $groupShares
+     */
+    public function setGroupShares($groupShares)
+    {
+        $this->groupShares = $groupShares;
+    }
 }
diff --git a/src/Wallabag/CoreBundle/Form/Type/EditGroupSharesType.php b/src/Wallabag/CoreBundle/Form/Type/EditGroupSharesType.php
new file mode 100644 (file)
index 0000000..2c2e3b3
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+namespace Wallabag\CoreBundle\Form\Type;
+
+use Symfony\Bridge\Doctrine\Form\Type\EntityType;
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\GroupBundle\Entity\Group;
+
+class EditGroupSharesType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add('groupshares', EntityType::class, [
+                'required' => true,
+                'class' => Group::class,
+                'choices' => $options['groups'],
+                'multiple' => true,
+                'expanded' => true,
+            ])
+            ->add('save', SubmitType::class, [
+                'label' => 'Share',
+            ])
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver)
+    {
+        $resolver->setDefaults([
+            'data_class' => Entry::class,
+        ]);
+        $resolver->setRequired('groups');
+    }
+
+    public function getBlockPrefix()
+    {
+        return 'group_shares';
+    }
+}
index 9bda4e15e81fcfd8d7e33635607fefa7db01c723..ade3d6bcad28ccad15971a6bade77d951bc272e2 100644 (file)
@@ -414,4 +414,17 @@ class EntryRepository extends EntityRepository
             ->getQuery()
             ->getResult();
     }
+
+    /**
+     * Find all entries for a group
+     *
+     * @param $groupId
+     * @return \Doctrine\ORM\QueryBuilder
+     */
+    public function findByGroup($groupId)
+       {
+               return $this->createQueryBuilder('p')
+                       ->innerJoin('p.groupShares', 'g', 'WITH', 'g.id = :group')
+                       ->setParameter(':group', $groupId);
+       }
 }
index 8f507c4017b7b2d06a29802921a0e46f55cca7d6..94bce4349fa92c97bf973771967fb6e1e297a4ef 100644 (file)
@@ -224,6 +224,7 @@ entry:
             delete_public_link: 'delete public link'
             export: 'Export'
             print: 'Print'
+            groups: Groups
             problem:
                 label: 'Problems?'
                 description: 'Does this article appear wrong?'
@@ -515,6 +516,31 @@ group:
         delete: Delete
         delete_confirm: Are you sure?
         back_to_list: Back to list
+        role_label: Default roles
+        access_label: Access
+        password_label: Password (if applicable)
+
+    roles:
+        readonly: Read only
+        write: Write access
+        manage_entries: Managing articles
+        manage_users: Managing members
+        admin: Administrator
+    access:
+        open: Open
+        request: On request
+        password: With password
+        invitation: Upon invitation
+        hidden: Upon invitation and private
+    tab_menu:
+        public: Public groups
+        own: My groups
+    manage:
+        label: Manage this group
+    entries:
+        label: Entries shared with this group
+    leave:
+        label: Leave
 
 user:
     page_title: Users management
index d909cf15c7ea8f5b0b1990b02a1d8587b6f2490f..007d5b2a3114df020e592e6f246199f2de8ff952 100644 (file)
@@ -240,6 +240,7 @@ entry:
             delete_public_link: "Supprimer le lien public"
             export: "Exporter"
             print: "Imprimer"
+            groups: Groupes
             problem:
                 label: "Un problème ?"
                 description: "Est-ce que cet article s’affiche mal ?"
@@ -549,6 +550,32 @@ group:
     tab_menu:
         public: Groupes publics
         own: Mes groupes
+    requests:
+        list: Liste des requêtes
+        sent: Requête envoyée
+        username: Utilisateur
+        action: Action
+    manage:
+        label: Gérer le groupe
+        title: Gérer le groupe
+    entries:
+        label: Liste des articles partagés avec ce groupe
+    leave:
+        label: Sortir de ce groupe
+    user:
+        inGroup: "{0}Il n'y a personne dans ce groupe|{1}Vous Ãªtes tout seul dans ce groupe|]1,Inf[Vous Ãªtes %count% utilisateurs dans ce groupe"
+        notInGroup: "{0}Il n'y a personne dans ce groupe|{1}Il y a un seul utilisateur dans ce groupe|]1,Inf[%count% utilisateurs dans ce groupe"
+    members:
+        empty: Le groupe est vide
+        name: Nom d'utilisateur
+        role: Rôle
+        action: Action
+        edit: Modifier les droits de l'utilisateur
+        exclude: Exclure l'utilisateur
+    edit_user:
+        title: Ã‰dition des droits de l'utilisateur
+        role: Rôle
+        cancel: Annuler
 
 user:
     page_title: "Gestion des utilisateurs"
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_share_groups.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/_share_groups.html.twig
new file mode 100644 (file)
index 0000000..5c81ccc
--- /dev/null
@@ -0,0 +1,24 @@
+<!-- Groups Modal -->
+<div id="groups-modal" class="modal bottom-sheet">
+    <div class="modal-content">
+        <div class="row">
+            <h4>Groups</h4>
+            <p>Select the groups you want to share this article with</p>
+            <form name="search" method="POST" action="{{ path('group-shares-entry', {'entry': entry.id})}}">
+                {% if form_errors(form) %}
+                    <span class="black-text">{{ form_errors(form) }}</span>
+                {% endif %}
+
+                {% if form_errors(form.groupshares) %}
+                    <span class="black-text">{{ form_errors(form.groupshares) }}</span>
+                {% endif %}
+
+                {{ form_widget(form.groupshares) }}
+                {{ form_widget(form.save, {'attr': {'class': 'modal-action modal-close waves-effect waves-light btn'}}) }}
+
+                {{ form_rest(form) }}
+            </form>
+
+        </div>
+    </div>
+</div>
index 4cff7bf2db489491618b6a61eb35c31086366ec4..05f51aa8f6b5fe6b2557652d29a722badbd14620 100644 (file)
             </div>
         </li>
 
+        {#{% if craue_setting('groups') %}#}
+            <li class="bold border-bottom hide-on-med-and-down">
+                <a class="waves-effect groups-button" onclick="$('#groups-modal').openModal();" title="{{ 'entry.view.left_menu.group'|trans }}">
+                    <i class="material-icons small">group</i>
+                    <span>{{ 'entry.view.left_menu.groups'|trans }}</span>
+                </a>
+            </li>
+        {#{% endif %}#}
+
         {% if craue_setting('show_printlink') %}
         <li class="bold border-bottom hide-on-med-and-down">
             <a class="waves-effect collapsible-header" title="{{ 'entry.view.left_menu.print'|trans }}" href="javascript: window.print();">
         </div>
     </div>
 
+    {{ render(controller( "WallabagCoreBundle:Entry:GroupShare", { 'entry': entry.id } )) }}
+
 <script id="annotationroutes" type="application/json">
 {
     "prefix": "",
index 575c77f2e01c4c56223fddcf1dd52ed1c317cce0..92b47dac57fb0c88cda39ab252273eb8db88af83 100644 (file)
                 <li class="bold {% if currentRoute starts with 'user_' %}active{% endif %}">
                     <a class="waves-effect" href="{{ path('user_index') }}">{{ 'menu.left.users_management'|trans }}</a>
                 </li>
-                <li class="bold {% if currentRoute starts with 'group_' %}active{% endif %}">
-                    <a class="waves-effect" href="{{ path('group_index') }}">{{ 'menu.left.groups_management'|trans }}</a>
-                </li>
 
                 <li class="bold border-bottom {% if currentRoute == 'craue_config_settings_modify' %}active{% endif %}">
                     <a class="waves-effect" href="{{ path('craue_config_settings_modify') }}">{{ 'menu.left.internal_settings'|trans }}</a>
                 </li>
             {% endif %}
+            <li class="bold {% if currentRoute starts with 'group_' %}active{% endif %}">
+                <a class="waves-effect" href="{{ path('group_index') }}">{{ 'menu.left.groups_management'|trans }}</a>
+            </li>
             <li class="bold {% if currentRoute == 'import' %}active{% endif %}">
                 <a class="waves-effect" href="{{ path('import') }}">{{ 'menu.left.import'|trans }}</a>
             </li>
index 31a0c7b1304c759c284a46edc4b8e750792fdd82..7214d899c6380077048759de90db19d2c17c8fe0 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Wallabag\GroupBundle\Controller;
 
+use Pagerfanta\Adapter\ArrayAdapter;
 use Pagerfanta\Adapter\DoctrineORMAdapter;
 use Pagerfanta\Exception\OutOfRangeCurrentPageException;
 use Pagerfanta\Pagerfanta;
@@ -15,6 +16,7 @@ use Wallabag\GroupBundle\Entity\Group;
 use Wallabag\GroupBundle\Entity\UserGroup;
 use Wallabag\GroupBundle\Form\GroupType;
 use Wallabag\GroupBundle\Form\NewGroupType;
+use Wallabag\GroupBundle\Form\UserGroupType;
 use Wallabag\UserBundle\Entity\User;
 
 /**
@@ -210,4 +212,186 @@ class ManageController extends Controller
         }
         throw $this->createAccessDeniedException();
     }
+
+       /**
+        * @Route("/join/{group}", name="group_join")
+        * @param Group $group
+        * @return Response
+        */
+       public function joinGroupAction(Group $group): Response
+       {
+               $em = $this->getDoctrine()->getManager();
+
+               if ($group->getAcceptSystem() === Group::ACCESS_PASSWORD) {
+                       return $this->redirectToRoute('group_password', ['group' => $group->getId()]);
+               }
+               $this->getUser()->addAGroup($group, $group->getDefaultRole());
+
+               $em->flush();
+
+               return $this->redirect($this->generateUrl('group_index'), 302);
+       }
+
+       /**
+        * @Route("/manage/{group}/{page}", name="group-manage", defaults={"page" = "1"})
+        * @param Group $group
+        * @return Response
+        */
+       public function manageGroupUsersAction(Group $group, int $page): Response
+       {
+               if ($this->getUser()->getGroupRoleForUser($group) < Group::ROLE_MANAGE_USERS) {
+                       $this->createAccessDeniedException();
+               }
+
+               $members = $this->get('wallabag_user.user_repository')->findGroupMembers($group->getId());
+
+               $pagerAdapter = new DoctrineORMAdapter($members->getQuery(), true, false);
+               $pagerFanta = new Pagerfanta($pagerAdapter);
+               $pagerFanta->setMaxPerPage(9);
+
+               try {
+                       $pagerFanta->setCurrentPage($page);
+               } catch (OutOfRangeCurrentPageException $e) {
+                       if ($page > 1) {
+                               return $this->redirect($this->generateUrl('groups', ['page' => $pagerFanta->getNbPages()]), 302);
+                       }
+               }
+
+               return $this->render('WallabagGroupBundle:Manage:manage.html.twig', [
+                       'members' => $pagerFanta,
+                       'group' => $group,
+                       'currentPage' => $page,
+               ]);
+       }
+
+       /**
+        * @Route("/leave/{group}", name="group_leave")
+        * @param Group $group
+        * @return Response
+        */
+       public function leaveGroupAction(Group $group): Response
+       {
+               $logger = $this->get('logger');
+               $em = $this->getDoctrine()->getManager();
+               $removeGroup = false;
+
+               if ($this->getUser()->getGroupRoleForUser($group) == Group::ROLE_ADMIN) {
+                       $logger->info('User ' . $this->getUser()->getUsername() . ' is the admin for group ' . $group->getName());
+                       $newUser = $group->getUsers()->first();
+                       $newUser->setGroupRole($group, Group::ROLE_ADMIN);
+                       $logger->info('The new admin for group ' . $group->getName() . ' is user ' . $newUser->getUsername());
+               }
+
+               if ($group->getUsers()->count() <= 1) {
+                       $logger->info('User ' . $this->getUser()->getUsername() . ' was the last one on the group ' . $group->getName() . ' so it will be deleted');
+                       $removeGroup = true;
+               }
+
+               $logger->info('Removing user ' . $this->getUser()->getUsername() . ' from group ' . $group->getName());
+               $em->remove($this->getUser()->getUserGroupFromGroup($group));
+
+               if ($removeGroup) {
+                       $logger->info("Removing group " . $group->getName() . " as it doesn't contains users anymore");
+                       $em->remove($group);
+               }
+
+               $em->flush();
+               return $this->redirect($this->generateUrl('groups'), 302);
+       }
+
+       /**
+        * @Route("/requests/{group}/{page}", name="group-requests", defaults={"page" = "1"})
+        * @param Request $request
+        * @param int $page
+        * @return Response
+        */
+       public function showRequestsAction(Group $group, int $page): Response
+       {
+               if ($this->getUser()->getGroupRoleForUser($group) < Group::ROLE_MANAGE_USERS) {
+                       $this->createAccessDeniedException();
+               }
+
+               $requests = $group->getRequests();
+               $pagerAdapter = new ArrayAdapter($requests->toArray());
+
+               $pagerFanta = new Pagerfanta($pagerAdapter);
+               $pagerFanta->setMaxPerPage(9);
+
+               try {
+                       $pagerFanta->setCurrentPage($page);
+               } catch (OutOfRangeCurrentPageException $e) {
+                       if ($page > 1) {
+                               return $this->redirect($this->generateUrl('groups', ['page' => $pagerFanta->getNbPages()]), 302);
+                       }
+               }
+
+               return $this->render('WallabagGroupBundle:Manage:requests.html.twig', [
+                       'requests' => $pagerFanta,
+                       'group' => $group,
+                       'currentPage' => $page,
+               ]);
+       }
+
+       /**
+        * @Route("/activate/{group}/{user}/{accept}", name="group-activate", requirements={"accept" = "\d+"})
+        * @param Group $group
+        * @param User $user
+        * @param $accept
+        * @return Response
+        */
+       public function postRequestAction(Group $group, User $user, $accept): Response
+       {
+               if (!$this->getUser() < Group::ROLE_MANAGE_USERS) {
+                       $this->createAccessDeniedException("You don't have the rights to do this");
+               }
+
+               $em = $this->getDoctrine()->getManager();
+
+               $accept = $accept == 1;
+               $user->getUserGroupFromGroup($group)->setAccepted($accept);
+               if (!$accept) {
+                       $em->remove($user->getUserGroupFromGroup($group));
+               }
+
+               $em->flush();
+
+               return $this->redirectToRoute('group_index');
+       }
+
+       /**
+        * @Route("/user-edit/{group}/{user}", name="group-user-edit")
+        * @param Request $request
+        * @param Group $group
+        * @param User $user
+        * @return Response
+        */
+       public function editGroupUsersAction(Request $request, Group $group, User $user): Response
+       {
+               if ($this->getUser()->getGroupRoleForUser($group) < Group::ROLE_MANAGE_USERS) {
+                       $this->createAccessDeniedException();
+               }
+
+               $groupUser = $user->getUserGroupFromGroup($group);
+               $editForm = $this->createForm(UserGroupType::class, $groupUser);
+               $editForm->handleRequest($request);
+
+               if ($editForm->isSubmitted() && $editForm->isValid()) {
+                       $em = $this->getDoctrine()->getManager();
+                       $em->persist($groupUser);
+                       $em->flush();
+
+                       $this->get('session')->getFlashBag()->add(
+                               'notice',
+                               $this->get('translator')->trans('flashes.group.notice.user.edited', ['%user%' => $user->getUsername(), '%group%' => $group->getName()])
+                       );
+
+                       return $this->redirectToRoute('group-manage', ['group' => $group->getId()]);
+               }
+
+               return $this->render('WallabagGroupBundle:Manage:edit_user.html.twig', array(
+                       'user' => $user,
+                       'group' => $group,
+                       'edit_form' => $editForm->createView(),
+               ));
+       }
 }
index e8f814e4e05d407184ba02c2a64428af313ed66c..326fa6826fd1e288bcc6618d18e0c77f56811c3f 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-namespace Wallabag\GroupBundle\Form\Type;
+namespace Wallabag\GroupBundle\Form;
 
 use Wallabag\GroupBundle\Entity\Group;
 use Symfony\Component\Form\AbstractType;
@@ -23,7 +23,7 @@ class UserGroupType extends AbstractType
                 'choices' => [
                     'group.roles.readonly' => Group::ROLE_READ_ONLY,
                     'group.roles.write' => Group::ROLE_WRITE,
-                    'group.roles.manage_prez' => Group::ROLE_MANAGE_PREZ,
+                    'group.roles.manage_entries' => Group::ROLE_MANAGE_ENTRIES,
                     'group.roles.manage_users' => Group::ROLE_MANAGE_USERS,
                     'group.roles.admin' => Group::ROLE_ADMIN,
                 ],
@@ -40,7 +40,7 @@ class UserGroupType extends AbstractType
     public function configureOptions(OptionsResolver $resolver)
     {
         $resolver->setDefaults(array(
-            'data_class' => 'Strut\StrutBundle\Entity\UserGroup',
+            'data_class' => 'Wallabag\GroupBundle\Entity\UserGroup',
         ));
     }
 }
index 76e8427a0a913c0d4ff0d7e4c6d899bb64220747..618f7ed74cb22b77e24262f30269b6afb94a8a35 100644 (file)
@@ -1,3 +1,8 @@
 services:
     sha256salted_encoder:
-          class: Strut\StrutBundle\Service\Sha256Salted
\ No newline at end of file
+          class: Wallabag\GroupBundle\Service\Sha256Salted
+
+    wallabag_core.filter.type.entry:
+            class: Wallabag\GroupBundle\Form\UserGroupType
+            tags:
+                - { name: form.type }
\ No newline at end of file
diff --git a/src/Wallabag/GroupBundle/Resources/views/Manage/edit_user.html.twig b/src/Wallabag/GroupBundle/Resources/views/Manage/edit_user.html.twig
new file mode 100644 (file)
index 0000000..b777169
--- /dev/null
@@ -0,0 +1,26 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'group.edit_user.title'|trans }}{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-md-6">
+
+        {{ form_start(edit_form) }}
+        {{ form_errors(edit_form) }}
+
+        <div class="form-group">
+            {{ form_label(edit_form.role) }}
+            {{ form_errors(edit_form.role) }}
+            {{ form_widget(edit_form.role) }}
+        </div>
+
+        {{ form_widget(edit_form.save, {'attr': {'class': 'btn waves-effect'}}) }}
+        <a class="btn btn-default" href="{{ path('group-manage', {'group': group.id}) }}">{{ 'group.edit_user.cancel' | trans }}</a>
+        {{ form_widget(edit_form._token) }}
+        {{ form_end(edit_form) }}
+    </div>
+</div>
+
+{% endblock %}
index 01466e5200db7294802e7f88b2d4cd763eaf8695..35a70400889e25b90a8d295d697b72b79a5e8afb 100644 (file)
@@ -12,7 +12,7 @@
                         <p class="help">{{ 'group.description'|trans|raw }}</p>
 
                         {% if groups is not empty %}
-                            <table class="bordered">
+                            <table class="bordered responsive-table">
                                 <thead>
                                     <tr>
                                         <th>{{ 'group.form.name_label'|trans }}</th>
                                 {% for group in groups %}
                                     <tr>
                                         <td>{{ group.name }}</td>
-                                        <td></td>
                                         <td>
-                                            <a href="{{ path('group_edit', { 'id': group.id }) }}">{{ 'group.list.edit_action'|trans }}</a>
+                                            {% if app.user in group.users and app.user.inGroup(group) %}
+                                                {{ 'group.user.inGroup' | transchoice(group.users | length) }}
+                                            {% else %}
+                                                {{ 'group.user.notInGroup' | transchoice(group.users | length) }}
+                                            {% endif %}
+                                        </td>
+                                        <td>
+                                            {% if app.user in group.users and app.user.inGroup(group) %}
+                                                {% if app.user.getGroupRoleForUser(group) >= 5 %}
+                                                    <a href="{{ path('group_edit', { 'id': group.id }) }}" class="waves-effect waves-light btn tooltipped" data-delay="50" data-position="bottom" data-tooltip="{{ 'group.list.edit_action'|trans }}"><i class="material-icons">edit</i></a>
+                                                    <a href="{{ path('group-manage', { 'group': group.id }) }}" class="waves-effect waves-light btn tooltipped" data-delay="50" data-position="bottom" data-tooltip="{{ 'group.manage.label'|trans }}"><i class="material-icons">settings_applications</i></a>
+                                                {% endif %}
+                                                <a href="{{ path('group-presentations', { 'group': group.id }) }}" class="waves-effect waves-light btn tooltipped" data-delay="50" data-position="bottom" data-tooltip="{{ 'group.entries.label'|trans }}"><i class="material-icons">view_list</i></a>
+                                                <a href="{{ path('group_leave', { 'group': group.id }) }}" class="waves-effect waves-light btn red tooltipped" data-delay="50" data-position="bottom" data-tooltip="{{ 'group.leave.label'|trans }}"><i class="material-icons">clear</i></a>
+                                            {% elseif app.user in group.users and not app.user.inGroup(group) %}
+                                                {{ 'group.requests.sent' | trans }}
+                                            {% else %}
+                                                <a href="{{ path('group_join', { 'group': group.id }) }}" class="waves-effect waves-light btn tooltipped" data-tooltip="{{ 'group.join.label'|trans }}" data-delay="50" data-position="bottom">
+                                                    {% if group.acceptSystem == 3 %}
+                                                        <i class="material-icons md-18 vertical-align-middle" data-toggle="tooltip" data-placement="bottom" title="{{ 'group.join'|trans }}">lock</i>
+                                                    {% else %}
+                                                        <i class="material-icons" data-toggle="tooltip" data-placement="bottom" title="{{ 'group.join'|trans }}">input</i>
+                                                    {% endif %}
+                                                </a>
+                                            {% endif %}
                                         </td>
                                     </tr>
                                 {% endfor %}
diff --git a/src/Wallabag/GroupBundle/Resources/views/Manage/manage.html.twig b/src/Wallabag/GroupBundle/Resources/views/Manage/manage.html.twig
new file mode 100644 (file)
index 0000000..2226b29
--- /dev/null
@@ -0,0 +1,102 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'group.manage.title' |trans({ '%group%': group.name }) }}{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="input-field col s12">
+        <p>
+            {{ 'group.form.role_label' |trans }}:
+            <em>
+                {% if group.defaultRole == 1 %}
+                    {{ 'group.roles.readonly' | trans }}
+                {% elseif group.defaultRole == 2 %}
+                    {{ 'group.roles.write' | trans }}
+                {% elseif group.defaultRole == 3 %}
+                    {{ 'group.roles.manage_prez' | trans }}
+                {% elseif group.defaultRole == 5 %}
+                    {{ 'group.roles.manage_users' | trans }}
+                {% elseif group.defaultRole == 10 %}
+                    {{ 'group.roles.admin' | trans }}
+                {% else %}
+                    {{ 'group.roles.unknown' | trans }}
+                {% endif %}
+            </em>
+        </p>
+        <p>
+            {{ 'group.form.access_label' | trans }}:
+            <em>
+                {% if group.acceptSystem == 1 %}
+                    {{ 'group.access.open' | trans }}
+                {% elseif group.acceptSystem == 2 %}
+                    {{ 'group.access.request' | trans }}
+                {% elseif group.acceptSystem == 3 %}
+                    {{ 'group.access.password' | trans }}
+                {% elseif group.acceptSystem == 4 %}
+                    {{ 'group.access.invitation' | trans }}
+                {% elseif group.acceptSystem == 10 %}
+                    {{ 'group.access.hidden' | trans }}
+                {% else %}
+                    {{ 'group.access.unknown' | trans }}
+                {% endif %}
+            </em>
+        </p>
+        <a href="{{ path('group_edit', {'id' : group.id}) }}" class="btn waves-effect">{{ 'group.edit_group' | trans }}</a>
+        {% if group.acceptSystem == 2 %}
+            <a href="{{ path('group-requests', {'group' : group.id}) }}" class="btn waves-effect">{{ 'group.requests.list' | trans }} <span class="badge">{{ group.getRequests() | length }}</span></a>
+        {% elseif group.acceptSystem >= 4 %}
+            <a href="{{ path('group-invitations', {'group' : group.id}) }}" class="btn waves-effect">{{ 'group.edit.invitations' | trans }} <span class="badge">{{ group.getInvited() | length }}</span></a>
+        {% endif %}
+        <a href="{{ path('group_delete', { 'id': group.id }) }}" class="btn waves-effect red"><i class="material-icons md-18" data-toggle="tooltip" data-placement="bottom" title="{{ 'group.form.delete'|trans }}">delete</i></a>
+
+        {% if members | length > 1 %}
+            <table class="table">
+                <thead>
+                <tr>
+                    <th>{{ 'group.members.name'|trans }}</th>
+                    <th>{{ 'group.members.role' | trans }}</th>
+                    <th>{{ 'group.members.action'|trans }}</th>
+                </tr>
+                </thead>
+
+                <tbody>
+                {% for user in members %}
+                    {% if user != app.user %}
+                        <tr>
+                            <td>{{ user.username }}</td>
+                            <td>
+                                {% if user.getGroupRoleForUser(group) == 1 %}
+                                    {{ 'group.roles.readonly' | trans }}
+                                {% elseif user.getGroupRoleForUser(group) == 2 %}
+                                    {{ 'group.roles.write' | trans }}
+                                {% elseif user.getGroupRoleForUser(group) == 3 %}
+                                    {{ 'group.roles.manage_prez' | trans }}
+                                {% elseif user.getGroupRoleForUser(group) == 5 %}
+                                    {{ 'group.roles.manage_users' | trans }}
+                                {% elseif user.getGroupRoleForUser(group) == 10 %}
+                                    {{ 'group.roles.admin' | trans }}
+                                {% else %}
+                                    {{ 'group.roles.unknown' | trans }}
+                                {% endif %}
+                            </td>
+                            <td>
+                                <a href="{{ path('group-user-edit', { 'group': group.id, 'user': user.id }) }}" class="btn waves-effect"><i class="material-icons md-18" data-toggle="tooltip" data-placement="bottom" title="{{ 'group.members.edit'|trans }}">edit</i></a>
+                                <a class="btn waves-effect red" href="{{ path('group-user-exclude', { 'group': group.id, 'user': user.id }) }}"><i class="material-icons md-18" data-toggle="tooltip" data-placement="bottom" title="{{ 'group.members.exclude'|trans }}">clear</i></a>
+                            </td>
+                        </tr>
+                    {% endif %}
+                {% endfor %}
+                </tbody>
+            </table>
+        {% else %}
+                <p>{{ 'group.members.empty' | trans }}</p>
+        {% endif %}
+        <div class="pull-right">
+            {% if members.getNbPages > 1 %}
+                {{ pagerfanta(members, 'twitter_bootstrap3', {'proximity': 1}) }}
+            {% endif %}
+        </div>
+    </div>
+</div>
+{% endblock %}
diff --git a/src/Wallabag/GroupBundle/Resources/views/Manage/requests.html.twig b/src/Wallabag/GroupBundle/Resources/views/Manage/requests.html.twig
new file mode 100644 (file)
index 0000000..36d069c
--- /dev/null
@@ -0,0 +1,31 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'group.requests.list'|trans }}{% endblock %}
+
+{% block content %}
+<div class="row">
+    <div class="col s12">
+
+        <table class="table">
+            <thead>
+            <tr>
+                <th>{{ 'group.requests.username'|trans }}</th>
+                <th>{{ 'group.requests.action'|trans }}</th>
+            </tr>
+            </thead>
+
+            <tbody>
+            {% for request in requests %}
+                <tr>
+                    <td>{{ request.username }}</td>
+                    <td>
+                        <a class="btn waves-effect" href="{{ path('group-activate', {'group': group.id, 'user': request.id, 'accept': 1}) }}"><i class="material-icons">check</i></a>
+                        <a class="btn waves-effect red" href="{{ path('group-activate', {'group': group.id, 'user': request.id, 'accept': 2}) }}"><i class="material-icons">close</i></a>
+                    </td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        </table>
+    </div>
+</div>
+{% endblock %}
index 4f24b17adbc2cf2d25b849acc5c9af551d73c11f..4a52b186dc108a62f8624d047c0eb488db0af44c 100644 (file)
@@ -393,4 +393,13 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
 
         return $groups;
     }
+
+       /**
+        * @param Group $group
+        * @param $role
+        */
+       public function addAGroup(Group $group, $role)
+       {
+               $this->userGroups->add(new UserGroup($this, $group, $role));
+       }
 }
index 6adbe329fb5519f9308be0aafc39968451ad8f88..b4b13605f18d1248df6fe9e2b2b832f8868fb3b8 100644 (file)
@@ -58,11 +58,19 @@ class UserRepository extends EntityRepository
      *
      * @param string $term
      *
-     * @return QueryBuilder
+     * @return \Doctrine\ORM\QueryBuilder
      */
     public function getQueryBuilderForSearch($term)
     {
         return $this->createQueryBuilder('u')
             ->andWhere('lower(u.username) LIKE lower(:term) OR lower(u.email) LIKE lower(:term) OR lower(u.name) LIKE lower(:term)')->setParameter('term', '%'.$term.'%');
     }
+
+    public function findGroupMembers($groupid)
+    {
+        return $this->createQueryBuilder('u')
+            ->leftJoin('u.userGroups', 'usergroup')
+            ->where('usergroup.group = :group')->setParameter(':group', $groupid)
+            ->andWhere('usergroup.accepted = true');
+    }
 }
index 5fc6163efa199c46eb19691ecfa811aa4ad59ec4..9d5abcaf60b0beaa217be7378dea9d294aafe33c 100644 (file)
@@ -30,7 +30,7 @@
                                 {{ form_rest(searchForm) }}
                             </form>
                         </div>
-                        
+
                     </div>
 
                     <table class="bordered">