mirror of
https://github.com/wallabag/wallabag.git
synced 2025-01-09 16:35:27 +00:00
Merge pull request #3060 from wallabag/search-users
Search & paginate users
This commit is contained in:
commit
6b76ae3d1f
17 changed files with 257 additions and 119 deletions
|
@ -512,6 +512,8 @@ user:
|
||||||
# delete: Delete
|
# delete: Delete
|
||||||
# delete_confirm: Are you sure?
|
# delete_confirm: Are you sure?
|
||||||
# back_to_list: Back to list
|
# back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: Löschen
|
delete: Löschen
|
||||||
delete_confirm: Bist du sicher?
|
delete_confirm: Bist du sicher?
|
||||||
back_to_list: Zurück zur Liste
|
back_to_list: Zurück zur Liste
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: Ein Fehler ist aufgetreten
|
page_title: Ein Fehler ist aufgetreten
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: Delete
|
delete: Delete
|
||||||
delete_confirm: Are you sure?
|
delete_confirm: Are you sure?
|
||||||
back_to_list: Back to list
|
back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: An error occurred
|
page_title: An error occurred
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: Eliminar
|
delete: Eliminar
|
||||||
delete_confirm: ¿Estás seguro?
|
delete_confirm: ¿Estás seguro?
|
||||||
back_to_list: Volver a la lista
|
back_to_list: Volver a la lista
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: Ha ocurrido un error
|
page_title: Ha ocurrido un error
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
# delete: Delete
|
# delete: Delete
|
||||||
# delete_confirm: Are you sure?
|
# delete_confirm: Are you sure?
|
||||||
# back_to_list: Back to list
|
# back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -46,7 +46,7 @@ footer:
|
||||||
social: "Social"
|
social: "Social"
|
||||||
powered_by: "propulsé par"
|
powered_by: "propulsé par"
|
||||||
about: "À propos"
|
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:
|
config:
|
||||||
page_title: "Configuration"
|
page_title: "Configuration"
|
||||||
|
@ -71,16 +71,16 @@ config:
|
||||||
300_word: "Je lis environ 300 mots par minute"
|
300_word: "Je lis environ 300 mots par minute"
|
||||||
400_word: "Je lis environ 400 mots par minute"
|
400_word: "Je lis environ 400 mots par minute"
|
||||||
action_mark_as_read:
|
action_mark_as_read:
|
||||||
label: 'Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?'
|
label: "Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?"
|
||||||
redirect_homepage: "À la page d'accueil"
|
redirect_homepage: "À la page d’accueil"
|
||||||
redirect_current_page: 'À la page courante'
|
redirect_current_page: "À la page courante"
|
||||||
pocket_consumer_key_label: Clé d’authentification Pocket pour importer les données
|
pocket_consumer_key_label: "Clé d’authentification Pocket pour importer les données"
|
||||||
android_configuration: Configurez votre application Android
|
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_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."
|
help_items_per_page: "Vous pouvez définir le nombre d’articles 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_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_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_pocket_consumer_key: "Nécessaire pour l’import depuis Pocket. Vous pouvez le créer depuis votre compte Pocket."
|
||||||
form_rss:
|
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."
|
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"
|
token_label: "Jeton RSS"
|
||||||
|
@ -100,18 +100,18 @@ config:
|
||||||
twoFactorAuthentication_label: "Double authentification"
|
twoFactorAuthentication_label: "Double authentification"
|
||||||
help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
|
help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
|
||||||
delete:
|
delete:
|
||||||
title: Supprimer mon compte (attention danger !)
|
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é.
|
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)
|
confirm: "Vous êtes vraiment sûr ? (C’EST IRRÉVERSIBLE)"
|
||||||
button: 'Supprimer mon compte'
|
button: "Supprimer mon compte"
|
||||||
reset:
|
reset:
|
||||||
title: Réinitialisation (attention danger !)
|
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 !
|
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
|
annotations: "Supprimer TOUTES les annotations"
|
||||||
tags: Supprimer TOUS les tags
|
tags: "Supprimer TOUS les tags"
|
||||||
entries: Supprimer TOUS les articles
|
entries: "Supprimer TOUS les articles"
|
||||||
archived: Supprimer TOUS les articles archivés
|
archived: "Supprimer TOUS les articles archivés"
|
||||||
confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
|
confirm: "Êtes-vous vraiment vraiment sûr ? (C’EST IRRÉVERSIBLE)"
|
||||||
form_password:
|
form_password:
|
||||||
description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères."
|
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"
|
old_password_label: "Mot de passe actuel"
|
||||||
|
@ -164,7 +164,7 @@ entry:
|
||||||
archived: "Articles lus"
|
archived: "Articles lus"
|
||||||
filtered: "Articles filtrés"
|
filtered: "Articles filtrés"
|
||||||
filtered_tags: "Articles filtrés par tags :"
|
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"
|
untagged: "Article sans tag"
|
||||||
list:
|
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."
|
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_label: "A une photo"
|
||||||
preview_picture_help: "Photo"
|
preview_picture_help: "Photo"
|
||||||
language_label: "Langue"
|
language_label: "Langue"
|
||||||
http_status_label: 'Statut HTTP'
|
http_status_label: "Statut HTTP"
|
||||||
reading_time:
|
reading_time:
|
||||||
label: "Durée de lecture en minutes"
|
label: "Durée de lecture en minutes"
|
||||||
from: "de"
|
from: "de"
|
||||||
|
@ -298,32 +298,32 @@ howto:
|
||||||
bookmarklet:
|
bookmarklet:
|
||||||
description: "Glissez et déposez ce lien dans votre barre de favoris :"
|
description: "Glissez et déposez ce lien dans votre barre de favoris :"
|
||||||
shortcuts:
|
shortcuts:
|
||||||
page_description: Voici les raccourcis disponibles dans wallabag.
|
page_description: "Voici les raccourcis disponibles dans wallabag."
|
||||||
shortcut: Raccourci
|
shortcut: "Raccourci"
|
||||||
action: Action
|
action: "Action"
|
||||||
all_pages_title: Raccourcis disponibles dans toutes les pages
|
all_pages_title: "Raccourcis disponibles dans toutes les pages"
|
||||||
go_unread: Afficher les articles non lus
|
go_unread: "Afficher les articles non lus"
|
||||||
go_starred: Afficher les articles favoris
|
go_starred: "Afficher les articles favoris"
|
||||||
go_archive: Afficher les articles lus
|
go_archive: "Afficher les articles lus"
|
||||||
go_all: Afficher tous les articles
|
go_all: "Afficher tous les articles"
|
||||||
go_tags: Afficher les tags
|
go_tags: "Afficher les tags"
|
||||||
go_config: Aller à la configuration
|
go_config: "Aller à la configuration"
|
||||||
go_import: Aller aux imports
|
go_import: "Aller aux imports"
|
||||||
go_developers: Aller à la section Développeurs
|
go_developers: "Aller à la section Développeurs"
|
||||||
go_howto: Afficher l'aide (cette page !)
|
go_howto: "Afficher l’aide (cette page !)"
|
||||||
go_logout: Se déconnecter
|
go_logout: "Se déconnecter"
|
||||||
list_title: Raccourcis disponibles dans les pages de liste
|
list_title: "Raccourcis disponibles dans les pages de liste"
|
||||||
search: Afficher le formulaire de recherche
|
search: "Afficher le formulaire de recherche"
|
||||||
article_title: Raccourcis disponibles quand on affiche un article
|
article_title: "Raccourcis disponibles quand on affiche un article"
|
||||||
open_original: Ouvrir l'URL originale de l'article
|
open_original: "Ouvrir l’URL originale de l’article"
|
||||||
toggle_favorite: Changer le statut Favori de l'article
|
toggle_favorite: "Changer le statut Favori de l’article"
|
||||||
toggle_archive: Changer le status Lu de l'article
|
toggle_archive: "Changer le status Lu de l’article"
|
||||||
delete: Supprimer l'article
|
delete: "Supprimer l’article"
|
||||||
material_title: Raccourcis disponibles avec le thème Material uniquement
|
material_title: "Raccourcis disponibles avec le thème Material uniquement"
|
||||||
add_link: Ajouter un nouvel article
|
add_link: "Ajouter un nouvel article"
|
||||||
hide_form: Masquer le formulaire courant (recherche ou nouvel article)
|
hide_form: "Masquer le formulaire courant (recherche ou nouvel article)"
|
||||||
arrows_navigation: Naviguer à travers les articles
|
arrows_navigation: "Naviguer à travers les articles"
|
||||||
open_article: Afficher l'article sélectionné
|
open_article: "Afficher l’article sélectionné"
|
||||||
|
|
||||||
quickstart:
|
quickstart:
|
||||||
page_title: "Pour bien débuter"
|
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."
|
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"
|
see_untagged_entries: "Voir les articles sans tag"
|
||||||
new:
|
new:
|
||||||
add: 'Ajouter'
|
add: "Ajouter"
|
||||||
placeholder: 'Vous pouvez ajouter plusieurs tags, séparés par une virgule.'
|
placeholder: "Vous pouvez ajouter plusieurs tags, séparés par une virgule."
|
||||||
|
|
||||||
import:
|
import:
|
||||||
page_title: "Importer"
|
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."
|
how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour l’importer."
|
||||||
worker:
|
worker:
|
||||||
enabled: "Les imports sont asynchrones. Une fois l’import commencé un worker externe traitera les messages un par un. Le service activé est :"
|
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:
|
firefox:
|
||||||
page_title: "Import > 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>"
|
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"
|
back: "Retour"
|
||||||
|
|
||||||
user:
|
user:
|
||||||
page_title: Gestion des utilisateurs
|
page_title: "Gestion des utilisateurs"
|
||||||
new_user: Créer un nouvel utilisateur
|
new_user: "Créer un nouvel utilisateur"
|
||||||
edit_user: Éditer un utilisateur existant
|
edit_user: "Éditer un utilisateur existant"
|
||||||
description: Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)
|
description: "Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)"
|
||||||
list:
|
list:
|
||||||
actions: Actions
|
actions: "Actions"
|
||||||
edit_action: Éditer
|
edit_action: "Éditer"
|
||||||
yes: Oui
|
yes: "Oui"
|
||||||
no: Non
|
no: "Non"
|
||||||
create_new_one: Créer un nouvel utilisateur
|
create_new_one: "Créer un nouvel utilisateur"
|
||||||
form:
|
form:
|
||||||
username_label: "Nom d’utilisateur"
|
username_label: "Nom d’utilisateur"
|
||||||
name_label: "Nom"
|
name_label: "Nom"
|
||||||
|
@ -513,9 +513,11 @@ user:
|
||||||
delete: "Supprimer"
|
delete: "Supprimer"
|
||||||
delete_confirm: "Voulez-vous vraiment ?"
|
delete_confirm: "Voulez-vous vraiment ?"
|
||||||
back_to_list: "Revenir à la liste"
|
back_to_list: "Revenir à la liste"
|
||||||
|
search:
|
||||||
|
placeholder: "Filtrer par nom d’utilisateur ou email"
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: Une erreur est survenue
|
page_title: "Une erreur est survenue"
|
||||||
|
|
||||||
flashes:
|
flashes:
|
||||||
config:
|
config:
|
||||||
|
@ -528,10 +530,10 @@ flashes:
|
||||||
tagging_rules_updated: "Règles mises à jour"
|
tagging_rules_updated: "Règles mises à jour"
|
||||||
tagging_rules_deleted: "Règle supprimée"
|
tagging_rules_deleted: "Règle supprimée"
|
||||||
rss_token_updated: "Jeton RSS mis à jour"
|
rss_token_updated: "Jeton RSS mis à jour"
|
||||||
annotations_reset: Annotations supprimées
|
annotations_reset: "Annotations supprimées"
|
||||||
tags_reset: Tags supprimés
|
tags_reset: "Tags supprimés"
|
||||||
entries_reset: Articles supprimés
|
entries_reset: "Articles supprimés"
|
||||||
archived_reset: Articles archivés supprimés
|
archived_reset: "Articles archivés supprimés"
|
||||||
entry:
|
entry:
|
||||||
notice:
|
notice:
|
||||||
entry_already_saved: "Article déjà sauvegardé le %date%"
|
entry_already_saved: "Article déjà sauvegardé le %date%"
|
||||||
|
@ -563,6 +565,6 @@ flashes:
|
||||||
client_deleted: "Client %name% supprimé"
|
client_deleted: "Client %name% supprimé"
|
||||||
user:
|
user:
|
||||||
notice:
|
notice:
|
||||||
added: 'Utilisateur "%username%" ajouté'
|
added: "Utilisateur \"%username%\" ajouté"
|
||||||
updated: 'Utilisateur "%username%" mis à jour'
|
updated: "Utilisateur \"%username%\" mis à jour"
|
||||||
deleted: 'Utilisateur "%username%" supprimé'
|
deleted: "Utilisateur \"%username%\" supprimé"
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
# delete: Delete
|
# delete: Delete
|
||||||
# delete_confirm: Are you sure?
|
# delete_confirm: Are you sure?
|
||||||
# back_to_list: Back to list
|
# back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: 'Suprimir'
|
delete: 'Suprimir'
|
||||||
delete_confirm: 'Sètz segur ?'
|
delete_confirm: 'Sètz segur ?'
|
||||||
back_to_list: 'Tornar a la lista'
|
back_to_list: 'Tornar a la lista'
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: Una error s'es produsida
|
page_title: Una error s'es produsida
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: Usuń
|
delete: Usuń
|
||||||
delete_confirm: Jesteś pewien?
|
delete_confirm: Jesteś pewien?
|
||||||
back_to_list: Powrót do listy
|
back_to_list: Powrót do listy
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
page_title: Wystąpił błąd
|
page_title: Wystąpił błąd
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
delete: 'Apagar'
|
delete: 'Apagar'
|
||||||
delete_confirm: 'Tem certeza?'
|
delete_confirm: 'Tem certeza?'
|
||||||
back_to_list: 'Voltar para a lista'
|
back_to_list: 'Voltar para a lista'
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
# delete: Delete
|
# delete: Delete
|
||||||
# delete_confirm: Are you sure?
|
# delete_confirm: Are you sure?
|
||||||
# back_to_list: Back to list
|
# back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -513,6 +513,8 @@ user:
|
||||||
# delete: Delete
|
# delete: Delete
|
||||||
# delete_confirm: Are you sure?
|
# delete_confirm: Are you sure?
|
||||||
# back_to_list: Back to list
|
# back_to_list: Back to list
|
||||||
|
search:
|
||||||
|
# placeholder: Filter by username or email
|
||||||
|
|
||||||
error:
|
error:
|
||||||
# page_title: An error occurred
|
# page_title: An error occurred
|
||||||
|
|
|
@ -4,35 +4,21 @@ namespace Wallabag\UserBundle\Controller;
|
||||||
|
|
||||||
use FOS\UserBundle\Event\UserEvent;
|
use FOS\UserBundle\Event\UserEvent;
|
||||||
use FOS\UserBundle\FOSUserEvents;
|
use FOS\UserBundle\FOSUserEvents;
|
||||||
|
use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||||
|
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
||||||
|
use Pagerfanta\Pagerfanta;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||||
use Wallabag\UserBundle\Entity\User;
|
use Wallabag\UserBundle\Entity\User;
|
||||||
use Wallabag\CoreBundle\Entity\Config;
|
use Wallabag\UserBundle\Form\SearchUserType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User controller.
|
* User controller.
|
||||||
*/
|
*/
|
||||||
class ManageController extends 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.
|
* Creates a new User entity.
|
||||||
*
|
*
|
||||||
|
@ -146,4 +132,49 @@ class ManageController extends Controller
|
||||||
->getForm()
|
->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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/Wallabag/UserBundle/Form/SearchUserType.php
Normal file
29
src/Wallabag/UserBundle/Form/SearchUserType.php
Normal file
|
@ -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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,4 +52,17 @@ class UserRepository extends EntityRepository
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getSingleScalarResult();
|
->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.'%');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,37 +7,60 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card-panel">
|
<div class="card-panel">
|
||||||
|
{% if users.getNbPages > 1 %}
|
||||||
|
{{ pagerfanta(users, 'twitter_bootstrap_translated', {'proximity': 1}) }}
|
||||||
|
{% endif %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="input-field col s12">
|
<div class="col s6">
|
||||||
<p class="help">{{ 'user.description'|trans|raw }}</p>
|
<p class="help">{{ 'user.description'|trans|raw }}</p>
|
||||||
|
|
||||||
<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>
|
|
||||||
</div>
|
</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 %}
|
||||||
|
|
||||||
|
{{ 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ class ManageControllerTest extends WallabagCoreTestCase
|
||||||
{
|
{
|
||||||
$client = $this->getClient();
|
$client = $this->getClient();
|
||||||
|
|
||||||
$client->request('GET', '/users/');
|
$client->request('GET', '/users/list');
|
||||||
|
|
||||||
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
||||||
$this->assertContains('login', $client->getResponse()->headers->get('location'));
|
$this->assertContains('login', $client->getResponse()->headers->get('location'));
|
||||||
|
@ -22,7 +22,7 @@ class ManageControllerTest extends WallabagCoreTestCase
|
||||||
$client = $this->getClient();
|
$client = $this->getClient();
|
||||||
|
|
||||||
// Create a new user in the database
|
// 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/');
|
$this->assertEquals(200, $client->getResponse()->getStatusCode(), 'Unexpected HTTP status code for GET /users/');
|
||||||
$crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link());
|
$crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link());
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class ManageControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$client->submit($form);
|
$client->submit($form);
|
||||||
$client->followRedirect();
|
$client->followRedirect();
|
||||||
$crawler = $client->request('GET', '/users/');
|
$crawler = $client->request('GET', '/users/list');
|
||||||
|
|
||||||
// Check data in the show view
|
// Check data in the show view
|
||||||
$this->assertGreaterThan(0, $crawler->filter('td:contains("test_user")')->count(), 'Missing element td:contains("test_user")');
|
$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"
|
// 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"]');
|
$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());
|
$crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
|
||||||
|
|
||||||
// Delete the user
|
// Delete the user
|
||||||
|
@ -78,4 +78,22 @@ class ManageControllerTest extends WallabagCoreTestCase
|
||||||
|
|
||||||
$this->assertEquals('disabled', $disabled[0]);
|
$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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue