]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #3080 from wallabag/use-username-to-import
authorNicolas Lœuillet <nicolas@loeuillet.org>
Thu, 4 May 2017 13:19:16 +0000 (15:19 +0200)
committerGitHub <noreply@github.com>
Thu, 4 May 2017 13:19:16 +0000 (15:19 +0200)
Use username to import

17 files changed:
src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
src/Wallabag/UserBundle/Controller/ManageController.php
src/Wallabag/UserBundle/Form/SearchUserType.php [new file with mode: 0644]
src/Wallabag/UserBundle/Repository/UserRepository.php
src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig
tests/Wallabag/UserBundle/Controller/ManageControllerTest.php

index e5211b5730c69c6bbe84a6b617b25a7482013e40..57319af73d4ecc5e1f1d89097e63b6717c674fcd 100644 (file)
@@ -512,6 +512,8 @@ user:
         # delete: Delete
         # delete_confirm: Are you sure?
         # back_to_list: Back to list
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index 893a45648bfbd515d159c32534e452a4ad6fbe6b..a7bcecc6f5d57539bad8b655d6eb73cf1bfd9fbb 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: Löschen
         delete_confirm: Bist du sicher?
         back_to_list: Zurück zur Liste
+    search:
+        # placeholder: Filter by username or email
 
 error:
     page_title: Ein Fehler ist aufgetreten
index 4b74568304aa8a8078b407475a8b7dd354417879..1ef2874d26d2750713200168192efde7da84eee9 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: Delete
         delete_confirm: Are you sure?
         back_to_list: Back to list
+    search:
+        placeholder: Filter by username or email
 
 error:
     page_title: An error occurred
index 99d2585924902f3f9012bf9fb6869ab04cf802cf..6cd079b077352ffe8284a990a3900f17825785d5 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: Eliminar
         delete_confirm: ¿Estás seguro?
         back_to_list: Volver a la lista
+    search:
+        # placeholder: Filter by username or email
 
 error:
     page_title: Ha ocurrido un error
index ccd9d5557c715bd97664d5932cc11918a71beb7b..fb6e315ec6dc16a89d30743783526228c15249af 100644 (file)
@@ -513,6 +513,8 @@ user:
         # delete: Delete
         # delete_confirm: Are you sure?
         # back_to_list: Back to list
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index a0f100f7a138f9ddd9b259b01b45c54c64058841..ad886363550c7650670c5bc0b5fe1389b186d323 100644 (file)
@@ -46,7 +46,7 @@ footer:
         social: "Social"
         powered_by: "propulsé par"
         about: "À propos"
-    stats: Depuis le %user_creation%, vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
+    stats: "Depuis le %user_creation%, vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !"
 
 config:
     page_title: "Configuration"
@@ -71,16 +71,16 @@ config:
             300_word: "Je lis environ 300 mots par minute"
             400_word: "Je lis environ 400 mots par minute"
         action_mark_as_read:
-            label: 'Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?'
-            redirect_homepage: "À la page d'accueil"
-            redirect_current_page: 'À la page courante'
-        pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données
-        android_configuration: Configurez votre application Android
-        help_theme: "L'affichage de wallabag est personnalisable. C'est ici que vous choisissez le thème que vous préférez."
-        help_items_per_page: "Vous pouvez définir le nombre d'articles affichés sur chaque page."
+            label: "Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?"
+            redirect_homepage: "À la page daccueil"
+            redirect_current_page: "À la page courante"
+        pocket_consumer_key_label: "Clé d’authentification Pocket pour importer les données"
+        android_configuration: "Configurez votre application Android"
+        help_theme: "L’affichage de wallabag est personnalisable. C’est ici que vous choisissez le thème que vous préférez."
+        help_items_per_page: "Vous pouvez définir le nombre darticles affichés sur chaque page."
         help_reading_speed: "wallabag calcule une durée de lecture pour chaque article. Vous pouvez définir ici, grâce à cette liste déroulante, si vous lisez plus ou moins vite. wallabag recalculera la durée de lecture de chaque article."
-        help_language: "Vous pouvez définir la langue de l'interface de wallabag."
-        help_pocket_consumer_key: "Nécessaire pour l'import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket."
+        help_language: "Vous pouvez définir la langue de linterface de wallabag."
+        help_pocket_consumer_key: "Nécessaire pour limport depuis Pocket. Vous pouvez le créer depuis votre compte Pocket."
     form_rss:
         description: "Les flux RSS fournis par wallabag vous permettent de lire vos articles sauvegardés dans votre lecteur de flux préféré. Pour pouvoir les utiliser, vous devez d’abord créer un jeton."
         token_label: "Jeton RSS"
@@ -100,18 +100,18 @@ config:
         twoFactorAuthentication_label: "Double authentification"
         help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
         delete:
-            title: Supprimer mon compte (attention danger !)
-            description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté.
-            confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE)
-            button: 'Supprimer mon compte'
+            title: "Supprimer mon compte (attention danger !)"
+            description: "Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c’est IRRÉVERSIBLE). Vous serez ensuite déconnecté."
+            confirm: "Vous êtes vraiment sûr ? (C’EST IRRÉVERSIBLE)"
+            button: "Supprimer mon compte"
     reset:
-        title: Réinitialisation (attention danger !)
-        description: En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !
-        annotations: Supprimer TOUTES les annotations
-        tags: Supprimer TOUS les tags
-        entries: Supprimer TOUS les articles
-        archived: Supprimer TOUS les articles archivés
-        confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
+        title: "Réinitialisation (attention danger !)"
+        description: "En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !"
+        annotations: "Supprimer TOUTES les annotations"
+        tags: "Supprimer TOUS les tags"
+        entries: "Supprimer TOUS les articles"
+        archived: "Supprimer TOUS les articles archivés"
+        confirm: "Êtes-vous vraiment vraiment sûr ? (C’EST IRRÉVERSIBLE)"
     form_password:
         description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères."
         old_password_label: "Mot de passe actuel"
@@ -164,7 +164,7 @@ entry:
         archived: "Articles lus"
         filtered: "Articles filtrés"
         filtered_tags: "Articles filtrés par tags :"
-        filtered_search: 'Articles filtrés par recherche :'
+        filtered_search: "Articles filtrés par recherche :"
         untagged: "Article sans tag"
     list:
         number_on_the_page: "{0} Il n’y a pas d’article.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
@@ -188,7 +188,7 @@ entry:
         preview_picture_label: "A une photo"
         preview_picture_help: "Photo"
         language_label: "Langue"
-        http_status_label: 'Statut HTTP'
+        http_status_label: "Statut HTTP"
         reading_time:
             label: "Durée de lecture en minutes"
             from: "de"
@@ -298,32 +298,32 @@ howto:
     bookmarklet:
         description: "Glissez et déposez ce lien dans votre barre de favoris :"
     shortcuts:
-        page_description: Voici les raccourcis disponibles dans wallabag.
-        shortcut: Raccourci
-        action: Action
-        all_pages_title: Raccourcis disponibles dans toutes les pages
-        go_unread: Afficher les articles non lus
-        go_starred: Afficher les articles favoris
-        go_archive:  Afficher les articles lus
-        go_all: Afficher tous les articles
-        go_tags: Afficher les tags
-        go_config: Aller à la configuration
-        go_import: Aller aux imports
-        go_developers: Aller à la section Développeurs
-        go_howto: Afficher l'aide (cette page !)
-        go_logout: Se déconnecter
-        list_title: Raccourcis disponibles dans les pages de liste
-        search: Afficher le formulaire de recherche
-        article_title: Raccourcis disponibles quand on affiche un article
-        open_original: Ouvrir l'URL originale de l'article
-        toggle_favorite: Changer le statut Favori de l'article
-        toggle_archive: Changer le status Lu de l'article
-        delete: Supprimer l'article
-        material_title: Raccourcis disponibles avec le thème Material uniquement
-        add_link: Ajouter un nouvel article
-        hide_form: Masquer le formulaire courant (recherche ou nouvel article)
-        arrows_navigation: Naviguer à travers les articles
-        open_article: Afficher l'article sélectionné
+        page_description: "Voici les raccourcis disponibles dans wallabag."
+        shortcut: "Raccourci"
+        action: "Action"
+        all_pages_title: "Raccourcis disponibles dans toutes les pages"
+        go_unread: "Afficher les articles non lus"
+        go_starred: "Afficher les articles favoris"
+        go_archive:  "Afficher les articles lus"
+        go_all: "Afficher tous les articles"
+        go_tags: "Afficher les tags"
+        go_config: "Aller à la configuration"
+        go_import: "Aller aux imports"
+        go_developers: "Aller à la section Développeurs"
+        go_howto: "Afficher l’aide (cette page !)"
+        go_logout: "Se déconnecter"
+        list_title: "Raccourcis disponibles dans les pages de liste"
+        search: "Afficher le formulaire de recherche"
+        article_title: "Raccourcis disponibles quand on affiche un article"
+        open_original: "Ouvrir l’URL originale de l’article"
+        toggle_favorite: "Changer le statut Favori de l’article"
+        toggle_archive: "Changer le status Lu de l’article"
+        delete: "Supprimer l’article"
+        material_title: "Raccourcis disponibles avec le thème Material uniquement"
+        add_link: "Ajouter un nouvel article"
+        hide_form: "Masquer le formulaire courant (recherche ou nouvel article)"
+        arrows_navigation: "Naviguer à travers les articles"
+        open_article: "Afficher l’article sélectionné"
 
 quickstart:
     page_title: "Pour bien débuter"
@@ -385,8 +385,8 @@ tag:
         number_on_the_page: "{0} Il n’y a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
         see_untagged_entries: "Voir les articles sans tag"
     new:
-        add: 'Ajouter'
-        placeholder: 'Vous pouvez ajouter plusieurs tags, séparés par une virgule.'
+        add: "Ajouter"
+        placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule."
 
 import:
     page_title: "Importer"
@@ -420,7 +420,7 @@ import:
         how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer."
     worker:
         enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
-        download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l'import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d'activer les imports asynchrones."
+        download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l’import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons <strong>vivement</strong> d’activer les imports asynchrones."
     firefox:
         page_title: "Import > Firefox"
         description: "Cet outil va vous permettre d’importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde… ». Vous allez récupérer un fichier .json. </p>"
@@ -489,16 +489,16 @@ developer:
         back: "Retour"
 
 user:
-    page_title: Gestion des utilisateurs
-    new_user: Créer un nouvel utilisateur
-    edit_user: Éditer un utilisateur existant
-    description: Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)
+    page_title: "Gestion des utilisateurs"
+    new_user: "Créer un nouvel utilisateur"
+    edit_user: "Éditer un utilisateur existant"
+    description: "Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)"
     list:
-        actions: Actions
-        edit_action: Éditer
-        yes: Oui
-        no: Non
-        create_new_one: Créer un nouvel utilisateur
+        actions: "Actions"
+        edit_action: "Éditer"
+        yes: "Oui"
+        no: "Non"
+        create_new_one: "Créer un nouvel utilisateur"
     form:
         username_label: "Nom d’utilisateur"
         name_label: "Nom"
@@ -513,9 +513,11 @@ user:
         delete: "Supprimer"
         delete_confirm: "Voulez-vous vraiment ?"
         back_to_list: "Revenir à la liste"
+    search:
+        placeholder: "Filtrer par nom d’utilisateur ou email"
 
 error:
-    page_title: Une erreur est survenue
+    page_title: "Une erreur est survenue"
 
 flashes:
     config:
@@ -528,10 +530,10 @@ flashes:
             tagging_rules_updated: "Règles mises à jour"
             tagging_rules_deleted: "Règle supprimée"
             rss_token_updated: "Jeton RSS mis à jour"
-            annotations_reset: Annotations supprimées
-            tags_reset: Tags supprimés
-            entries_reset: Articles supprimés
-            archived_reset: Articles archivés supprimés
+            annotations_reset: "Annotations supprimées"
+            tags_reset: "Tags supprimés"
+            entries_reset: "Articles supprimés"
+            archived_reset: "Articles archivés supprimés"
     entry:
         notice:
             entry_already_saved: "Article déjà sauvegardé le %date%"
@@ -563,6 +565,6 @@ flashes:
             client_deleted: "Client %name% supprimé"
     user:
         notice:
-            added: 'Utilisateur "%username%" ajouté'
-            updated: 'Utilisateur "%username%" mis à jour'
-            deleted: 'Utilisateur "%username%" supprimé'
+            added: "Utilisateur \"%username%\" ajouté"
+            updated: "Utilisateur \"%username%\" mis à jour"
+            deleted: "Utilisateur \"%username%\" supprimé"
index 374071ce0df95c8bf0a5a695699e7edc39e88cac..5a9605ff2c4ae85d58c870f927dc1d2ac68d3230 100644 (file)
@@ -513,6 +513,8 @@ user:
         # delete: Delete
         # delete_confirm: Are you sure?
         # back_to_list: Back to list
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index b01c611bc1f5183327cc90f6cfac943f21b04c29..942bc257863373a0ec5017625594e2c67addc657 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: 'Suprimir'
         delete_confirm: 'Sètz segur ?'
         back_to_list: 'Tornar a la lista'
+    search:
+        # placeholder: Filter by username or email
 
 error:
     page_title: Una error s'es produsida
index d76ac32818e5db110fa0d6ed440549d402d00363..fea90440a50a432f0bd844b8f080a2d91bb1fc92 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: Usuń
         delete_confirm: Jesteś pewien?
         back_to_list: Powrót do listy
+    search:
+        # placeholder: Filter by username or email
 
 error:
     page_title: Wystąpił błąd
index 98dfcd25788354a31c0b6c2b836ddc3ab2f2146e..c59991f89931263c6ebe02cfe78683a63155ae29 100644 (file)
@@ -513,6 +513,8 @@ user:
         delete: 'Apagar'
         delete_confirm: 'Tem certeza?'
         back_to_list: 'Voltar para a lista'
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index 8c07c13f3ab059b19e5bec3436e41b561bbdaf80..5846b7cc30076d3f8604b6e5a8b477c3e437cb27 100644 (file)
@@ -513,6 +513,8 @@ user:
         # delete: Delete
         # delete_confirm: Are you sure?
         # back_to_list: Back to list
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index bd21cb6743a1af6cc845f16d7f88bee438de3827..430fb96bcf129fe2f9c8f29f145f5413a55d8bad 100644 (file)
@@ -513,6 +513,8 @@ user:
         # delete: Delete
         # delete_confirm: Are you sure?
         # back_to_list: Back to list
+    search:
+        # placeholder: Filter by username or email
 
 error:
     # page_title: An error occurred
index 92ee2b4162649fad67e3158ca91c105d13e58ff4..1c5c86d45501f41c987edba0efa48bf320f3fa93 100644 (file)
@@ -4,35 +4,21 @@ namespace Wallabag\UserBundle\Controller;
 
 use FOS\UserBundle\Event\UserEvent;
 use FOS\UserBundle\FOSUserEvents;
+use Pagerfanta\Adapter\DoctrineORMAdapter;
+use Pagerfanta\Exception\OutOfRangeCurrentPageException;
+use Pagerfanta\Pagerfanta;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 use Wallabag\UserBundle\Entity\User;
-use Wallabag\CoreBundle\Entity\Config;
+use Wallabag\UserBundle\Form\SearchUserType;
 
 /**
  * User controller.
  */
 class ManageController extends Controller
 {
-    /**
-     * Lists all User entities.
-     *
-     * @Route("/", name="user_index")
-     * @Method("GET")
-     */
-    public function indexAction()
-    {
-        $em = $this->getDoctrine()->getManager();
-
-        $users = $em->getRepository('WallabagUserBundle:User')->findAll();
-
-        return $this->render('WallabagUserBundle:Manage:index.html.twig', array(
-            'users' => $users,
-        ));
-    }
-
     /**
      * Creates a new User entity.
      *
@@ -146,4 +132,49 @@ class ManageController extends Controller
             ->getForm()
         ;
     }
+
+    /**
+     * @param Request $request
+     * @param int     $page
+     *
+     * @Route("/list/{page}", name="user_index", defaults={"page" = 1})
+     *
+     * Default parameter for page is hardcoded (in duplication of the defaults from the Route)
+     * because this controller is also called inside the layout template without any page as argument
+     *
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    public function searchFormAction(Request $request, $page = 1)
+    {
+        $em = $this->getDoctrine()->getManager();
+        $qb = $em->getRepository('WallabagUserBundle:User')->createQueryBuilder('u');
+
+        $form = $this->createForm(SearchUserType::class);
+        $form->handleRequest($request);
+
+        if ($form->isSubmitted() && $form->isValid()) {
+            $this->get('logger')->info('searching users');
+
+            $searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : '');
+
+            $qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm);
+        }
+
+        $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
+        $pagerFanta = new Pagerfanta($pagerAdapter);
+        $pagerFanta->setMaxPerPage(50);
+
+        try {
+            $pagerFanta->setCurrentPage($page);
+        } catch (OutOfRangeCurrentPageException $e) {
+            if ($page > 1) {
+                return $this->redirect($this->generateUrl('user_index', ['page' => $pagerFanta->getNbPages()]), 302);
+            }
+        }
+
+        return $this->render('WallabagUserBundle:Manage:index.html.twig', [
+            'searchForm' => $form->createView(),
+            'users' => $pagerFanta,
+        ]);
+    }
 }
diff --git a/src/Wallabag/UserBundle/Form/SearchUserType.php b/src/Wallabag/UserBundle/Form/SearchUserType.php
new file mode 100644 (file)
index 0000000..9ce46ee
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+namespace Wallabag\UserBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+
+class SearchUserType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->setMethod('GET')
+            ->add('term', TextType::class, [
+                'required' => true,
+                'label' => 'user.new.form_search.term_label',
+            ])
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver)
+    {
+        $resolver->setDefaults([
+            'csrf_protection' => false,
+        ]);
+    }
+}
index f913f52dd5beaf0fed96d38c940d230a98be07ba..6adbe329fb5519f9308be0aafc39968451ad8f88 100644 (file)
@@ -52,4 +52,17 @@ class UserRepository extends EntityRepository
             ->getQuery()
             ->getSingleScalarResult();
     }
+
+    /**
+     * Retrieves users filtered with a search term.
+     *
+     * @param string $term
+     *
+     * @return 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.'%');
+    }
 }
index daba29e43ab54171d58b1c56654d074a45a30c7d..15002632cfaabaf5c9b353d55281e0aa2b86ba6a 100644 (file)
@@ -7,37 +7,60 @@
     <div class="row">
         <div class="col s12">
             <div class="card-panel">
+                {% if users.getNbPages > 1 %}
+                    {{ pagerfanta(users, 'twitter_bootstrap_translated', {'proximity': 1}) }}
+                {% endif %}
                 <div class="row">
-                    <div class="input-field col s12">
+                    <div class="col s6">
                         <p class="help">{{ 'user.description'|trans|raw }}</p>
+                    </div>
+                    <div class="col s6">
+                        <div class="input-field">
+                            <form name="search_users" method="GET" action="{{ path('user_index')}}">
+                                {% if form_errors(searchForm) %}
+                                    <span class="black-text">{{ form_errors(searchForm) }}</span>
+                                {% endif %}
+
+                                {% if form_errors(searchForm.term) %}
+                                    <span class="black-text">{{ form_errors(searchForm.term) }}</span>
+                                {% endif %}
 
-                        <table class="bordered">
-                            <thead>
-                                <tr>
-                                    <th>{{ 'user.form.username_label'|trans }}</th>
-                                    <th>{{ 'user.form.email_label'|trans }}</th>
-                                    <th>{{ 'user.form.last_login_label'|trans }}</th>
-                                    <th>{{ 'user.list.actions'|trans }}</th>
-                                </tr>
-                            </thead>
-                            <tbody>
-                            {% for user in users %}
-                                <tr>
-                                    <td>{{ user.username }}</td>
-                                    <td>{{ user.email }}</td>
-                                    <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td>
-                                    <td>
-                                        <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a>
-                                    </td>
-                                </tr>
-                            {% endfor %}
-                            </tbody>
-                        </table>
-                        <br />
-                        <p>
-                            <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a>
-                        </p>
+                                {{ form_widget(searchForm.term, { 'attr': {'autocomplete': 'off', 'placeholder': 'user.search.placeholder'} }) }}
+
+                                {{ form_rest(searchForm) }}
+                            </form>
+                        </div>
                     </div>
+
+                    <table class="bordered">
+                        <thead>
+                            <tr>
+                                <th>{{ 'user.form.username_label'|trans }}</th>
+                                <th>{{ 'user.form.email_label'|trans }}</th>
+                                <th>{{ 'user.form.last_login_label'|trans }}</th>
+                                <th>{{ 'user.list.actions'|trans }}</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                        {% for user in users %}
+                            <tr>
+                                <td>{{ user.username }}</td>
+                                <td>{{ user.email }}</td>
+                                <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td>
+                                <td>
+                                    <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a>
+                                </td>
+                            </tr>
+                        {% endfor %}
+                        </tbody>
+                    </table>
+                    <br />
+                    <p>
+                        <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a>
+                    </p>
+                    {% if users.getNbPages > 1 %}
+                        {{ pagerfanta(users, 'twitter_bootstrap_translated', {'proximity': 1}) }}
+                    {% endif %}
                 </div>
             </div>
         </div>
index 4faddfc4da7a6e81616a285e1dc3d882f3c61161..44b9a0301c51e11b4ba255c6b0c13a266f6f0af8 100644 (file)
@@ -10,7 +10,7 @@ class ManageControllerTest extends WallabagCoreTestCase
     {
         $client = $this->getClient();
 
-        $client->request('GET', '/users/');
+        $client->request('GET', '/users/list');
 
         $this->assertEquals(302, $client->getResponse()->getStatusCode());
         $this->assertContains('login', $client->getResponse()->headers->get('location'));
@@ -22,7 +22,7 @@ class ManageControllerTest extends WallabagCoreTestCase
         $client = $this->getClient();
 
         // Create a new user in the database
-        $crawler = $client->request('GET', '/users/');
+        $crawler = $client->request('GET', '/users/list');
         $this->assertEquals(200, $client->getResponse()->getStatusCode(), 'Unexpected HTTP status code for GET /users/');
         $crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link());
 
@@ -36,7 +36,7 @@ class ManageControllerTest extends WallabagCoreTestCase
 
         $client->submit($form);
         $client->followRedirect();
-        $crawler = $client->request('GET', '/users/');
+        $crawler = $client->request('GET', '/users/list');
 
         // Check data in the show view
         $this->assertGreaterThan(0, $crawler->filter('td:contains("test_user")')->count(), 'Missing element td:contains("test_user")');
@@ -57,7 +57,7 @@ class ManageControllerTest extends WallabagCoreTestCase
         // Check the element contains an attribute with value equals "Foo User"
         $this->assertGreaterThan(0, $crawler->filter('[value="Foo User"]')->count(), 'Missing element [value="Foo User"]');
 
-        $crawler = $client->request('GET', '/users/');
+        $crawler = $client->request('GET', '/users/list');
         $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
 
         // Delete the user
@@ -78,4 +78,22 @@ class ManageControllerTest extends WallabagCoreTestCase
 
         $this->assertEquals('disabled', $disabled[0]);
     }
+
+    public function testUserSearch()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        // Search on unread list
+        $crawler = $client->request('GET', '/users/list');
+
+        $form = $crawler->filter('form[name=search_users]')->form();
+        $data = [
+            'search_user[term]' => 'admin',
+        ];
+
+        $crawler = $client->submit($form, $data);
+
+        $this->assertCount(2, $crawler->filter('tr')); // 1 result + table header
+    }
 }