aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag
diff options
context:
space:
mode:
authorNicolas LÅ“uillet <nicolas@loeuillet.org>2015-08-07 22:20:30 +0200
committerNicolas LÅ“uillet <nicolas@loeuillet.org>2015-08-12 09:01:29 +0200
commit2686457448372543fdf4f1fc54c4fd20f0f02c2c (patch)
tree485eeecc3bd3db3613d47de25662d5c9163e4afe /src/Wallabag
parentfedaf005377e6d62ff0986f7f54afef3287a6451 (diff)
downloadwallabag-2686457448372543fdf4f1fc54c4fd20f0f02c2c.tar.gz
wallabag-2686457448372543fdf4f1fc54c4fd20f0f02c2c.tar.zst
wallabag-2686457448372543fdf4f1fc54c4fd20f0f02c2c.zip
store estimated reading time / filters on reading time
Diffstat (limited to 'src/Wallabag')
-rw-r--r--src/Wallabag/CoreBundle/Controller/EntryController.php66
-rw-r--r--src/Wallabag/CoreBundle/Controller/RssController.php17
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php4
-rw-r--r--src/Wallabag/CoreBundle/Filter/EntryFilterType.php28
-rwxr-xr-xsrc/Wallabag/CoreBundle/Helper/Tools.php12
-rw-r--r--src/Wallabag/CoreBundle/Repository/EntryRepository.php36
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig7
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig4
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css8
-rwxr-xr-xsrc/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css50
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig5
-rwxr-xr-xsrc/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css2
-rw-r--r--src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php19
-rw-r--r--src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php13
14 files changed, 184 insertions, 87 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php
index 29e0ffb0..8894690c 100644
--- a/src/Wallabag/CoreBundle/Controller/EntryController.php
+++ b/src/Wallabag/CoreBundle/Controller/EntryController.php
@@ -9,6 +9,9 @@ use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\CoreBundle\Service\Extractor; 9use Wallabag\CoreBundle\Service\Extractor;
10use Wallabag\CoreBundle\Form\Type\NewEntryType; 10use Wallabag\CoreBundle\Form\Type\NewEntryType;
11use Wallabag\CoreBundle\Form\Type\EditEntryType; 11use Wallabag\CoreBundle\Form\Type\EditEntryType;
12use Wallabag\CoreBundle\Filter\EntryFilterType;
13use Pagerfanta\Adapter\DoctrineORMAdapter;
14use Pagerfanta\Pagerfanta;
12 15
13class EntryController extends Controller 16class EntryController extends Controller
14{ 17{
@@ -89,22 +92,39 @@ class EntryController extends Controller
89 /** 92 /**
90 * Shows unread entries for current user. 93 * Shows unread entries for current user.
91 * 94 *
95 * @param Request $request
96 * @param int $page
97 *
92 * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"}) 98 * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"})
93 * 99 *
94 * @return \Symfony\Component\HttpFoundation\Response 100 * @return \Symfony\Component\HttpFoundation\Response
95 */ 101 */
96 public function showUnreadAction($page) 102 public function showUnreadAction(Request $request, $page)
97 { 103 {
98 $entries = $this->getDoctrine() 104 $form = $this->get('form.factory')->create(new EntryFilterType());
105
106 $filterBuilder = $this->getDoctrine()
99 ->getRepository('WallabagCoreBundle:Entry') 107 ->getRepository('WallabagCoreBundle:Entry')
100 ->findUnreadByUser($this->getUser()->getId()); 108 ->findUnreadByUser($this->getUser()->getId());
101 109
110 if ($request->query->has($form->getName())) {
111 // manually bind values from the request
112 $form->submit($request->query->get($form->getName()));
113
114 // build the query from the given form object
115 $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
116 }
117
118 $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
119 $entries = new Pagerfanta($pagerAdapter);
120
102 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); 121 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
103 $entries->setCurrentPage($page); 122 $entries->setCurrentPage($page);
104 123
105 return $this->render( 124 return $this->render(
106 'WallabagCoreBundle:Entry:entries.html.twig', 125 'WallabagCoreBundle:Entry:entries.html.twig',
107 array( 126 array(
127 'form' => $form->createView(),
108 'entries' => $entries, 128 'entries' => $entries,
109 'currentPage' => $page 129 'currentPage' => $page
110 ) 130 )
@@ -114,22 +134,39 @@ class EntryController extends Controller
114 /** 134 /**
115 * Shows read entries for current user. 135 * Shows read entries for current user.
116 * 136 *
137 * @param Request $request
138 * @param int $page
139 *
117 * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"}) 140 * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"})
118 * 141 *
119 * @return \Symfony\Component\HttpFoundation\Response 142 * @return \Symfony\Component\HttpFoundation\Response
120 */ 143 */
121 public function showArchiveAction($page) 144 public function showArchiveAction(Request $request, $page)
122 { 145 {
123 $entries = $this->getDoctrine() 146 $form = $this->get('form.factory')->create(new EntryFilterType());
147
148 $filterBuilder = $this->getDoctrine()
124 ->getRepository('WallabagCoreBundle:Entry') 149 ->getRepository('WallabagCoreBundle:Entry')
125 ->findArchiveByUser($this->getUser()->getId()); 150 ->findArchiveByUser($this->getUser()->getId());
126 151
152 if ($request->query->has($form->getName())) {
153 // manually bind values from the request
154 $form->submit($request->query->get($form->getName()));
155
156 // build the query from the given form object
157 $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
158 }
159
160 $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
161 $entries = new Pagerfanta($pagerAdapter);
162
127 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); 163 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
128 $entries->setCurrentPage($page); 164 $entries->setCurrentPage($page);
129 165
130 return $this->render( 166 return $this->render(
131 'WallabagCoreBundle:Entry:entries.html.twig', 167 'WallabagCoreBundle:Entry:entries.html.twig',
132 array( 168 array(
169 'form' => $form->createView(),
133 'entries' => $entries, 170 'entries' => $entries,
134 'currentPage' => $page 171 'currentPage' => $page
135 ) 172 )
@@ -139,22 +176,39 @@ class EntryController extends Controller
139 /** 176 /**
140 * Shows starred entries for current user. 177 * Shows starred entries for current user.
141 * 178 *
179 * @param Request $request
180 * @param int $page
181 *
142 * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"}) 182 * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
143 * 183 *
144 * @return \Symfony\Component\HttpFoundation\Response 184 * @return \Symfony\Component\HttpFoundation\Response
145 */ 185 */
146 public function showStarredAction($page) 186 public function showStarredAction(Request $request, $page)
147 { 187 {
148 $entries = $this->getDoctrine() 188 $form = $this->get('form.factory')->create(new EntryFilterType());
189
190 $filterBuilder = $this->getDoctrine()
149 ->getRepository('WallabagCoreBundle:Entry') 191 ->getRepository('WallabagCoreBundle:Entry')
150 ->findStarredByUser($this->getUser()->getId()); 192 ->findStarredByUser($this->getUser()->getId());
151 193
194 if ($request->query->has($form->getName())) {
195 // manually bind values from the request
196 $form->submit($request->query->get($form->getName()));
197
198 // build the query from the given form object
199 $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
200 }
201
202 $pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
203 $entries = new Pagerfanta($pagerAdapter);
204
152 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); 205 $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
153 $entries->setCurrentPage($page); 206 $entries->setCurrentPage($page);
154 207
155 return $this->render( 208 return $this->render(
156 'WallabagCoreBundle:Entry:entries.html.twig', 209 'WallabagCoreBundle:Entry:entries.html.twig',
157 array( 210 array(
211 'form' => $form->createView(),
158 'entries' => $entries, 212 'entries' => $entries,
159 'currentPage' => $page 213 'currentPage' => $page
160 ) 214 )
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php
index 8428dce0..0558c53b 100644
--- a/src/Wallabag/CoreBundle/Controller/RssController.php
+++ b/src/Wallabag/CoreBundle/Controller/RssController.php
@@ -7,6 +7,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
7use Symfony\Bundle\FrameworkBundle\Controller\Controller; 7use Symfony\Bundle\FrameworkBundle\Controller\Controller;
8use Wallabag\CoreBundle\Entity\User; 8use Wallabag\CoreBundle\Entity\User;
9use Wallabag\CoreBundle\Entity\Entry; 9use Wallabag\CoreBundle\Entity\Entry;
10use Pagerfanta\Adapter\DoctrineORMAdapter;
11use Pagerfanta\Pagerfanta;
10 12
11class RssController extends Controller 13class RssController extends Controller
12{ 14{
@@ -20,12 +22,15 @@ class RssController extends Controller
20 */ 22 */
21 public function showUnreadAction(User $user) 23 public function showUnreadAction(User $user)
22 { 24 {
23 $entries = $this->getDoctrine() 25 $qb = $this->getDoctrine()
24 ->getRepository('WallabagCoreBundle:Entry') 26 ->getRepository('WallabagCoreBundle:Entry')
25 ->findUnreadByUser( 27 ->findUnreadByUser(
26 $user->getId() 28 $user->getId()
27 ); 29 );
28 30
31 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
32 $entries = new Pagerfanta($pagerAdapter);
33
29 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); 34 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
30 $entries->setMaxPerPage($perPage); 35 $entries->setMaxPerPage($perPage);
31 36
@@ -45,12 +50,15 @@ class RssController extends Controller
45 */ 50 */
46 public function showArchiveAction(User $user) 51 public function showArchiveAction(User $user)
47 { 52 {
48 $entries = $this->getDoctrine() 53 $qb = $this->getDoctrine()
49 ->getRepository('WallabagCoreBundle:Entry') 54 ->getRepository('WallabagCoreBundle:Entry')
50 ->findArchiveByUser( 55 ->findArchiveByUser(
51 $user->getId() 56 $user->getId()
52 ); 57 );
53 58
59 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
60 $entries = new Pagerfanta($pagerAdapter);
61
54 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); 62 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
55 $entries->setMaxPerPage($perPage); 63 $entries->setMaxPerPage($perPage);
56 64
@@ -70,12 +78,15 @@ class RssController extends Controller
70 */ 78 */
71 public function showStarredAction(User $user) 79 public function showStarredAction(User $user)
72 { 80 {
73 $entries = $this->getDoctrine() 81 $qb = $this->getDoctrine()
74 ->getRepository('WallabagCoreBundle:Entry') 82 ->getRepository('WallabagCoreBundle:Entry')
75 ->findStarredByUser( 83 ->findStarredByUser(
76 $user->getId() 84 $user->getId()
77 ); 85 );
78 86
87 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
88 $entries = new Pagerfanta($pagerAdapter);
89
79 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); 90 $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
80 $entries->setMaxPerPage($perPage); 91 $entries->setMaxPerPage($perPage);
81 92
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index f139bbac..9aebc55b 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
7use Symfony\Component\Validator\Constraints as Assert; 7use Symfony\Component\Validator\Constraints as Assert;
8use Hateoas\Configuration\Annotation as Hateoas; 8use Hateoas\Configuration\Annotation as Hateoas;
9use JMS\Serializer\Annotation\XmlRoot; 9use JMS\Serializer\Annotation\XmlRoot;
10use Wallabag\CoreBundle\Helper\Tools;
10 11
11/** 12/**
12 * Entry. 13 * Entry.
@@ -96,7 +97,7 @@ class Entry
96 /** 97 /**
97 * @var int 98 * @var int
98 * 99 *
99 * @ORM\Column(name="reading_type", type="integer", nullable=true) 100 * @ORM\Column(name="reading_time", type="integer", nullable=true)
100 */ 101 */
101 private $readingTime; 102 private $readingTime;
102 103
@@ -264,6 +265,7 @@ class Entry
264 public function setContent($content) 265 public function setContent($content)
265 { 266 {
266 $this->content = $content; 267 $this->content = $content;
268 $this->readingTime = Tools::getReadingTime($content);
267 269
268 return $this; 270 return $this;
269 } 271 }
diff --git a/src/Wallabag/CoreBundle/Filter/EntryFilterType.php b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php
new file mode 100644
index 00000000..636ba324
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Filter/EntryFilterType.php
@@ -0,0 +1,28 @@
1<?php
2
3namespace Wallabag\CoreBundle\Filter;
4
5use Symfony\Component\Form\AbstractType;
6use Symfony\Component\Form\FormBuilderInterface;
7use Symfony\Component\OptionsResolver\OptionsResolver;
8
9class EntryFilterType extends AbstractType
10{
11 public function buildForm(FormBuilderInterface $builder, array $options)
12 {
13 $builder->add('readingTime', 'filter_number_range');
14 }
15
16 public function getName()
17 {
18 return 'entry_filter';
19 }
20
21 public function configureOptions(OptionsResolver $resolver)
22 {
23 $resolver->setDefaults(array(
24 'csrf_protection' => false,
25 'validation_groups' => array('filtering')
26 ));
27 }
28}
diff --git a/src/Wallabag/CoreBundle/Helper/Tools.php b/src/Wallabag/CoreBundle/Helper/Tools.php
index be29ab99..d368ee71 100755
--- a/src/Wallabag/CoreBundle/Helper/Tools.php
+++ b/src/Wallabag/CoreBundle/Helper/Tools.php
@@ -118,4 +118,16 @@ final class Tools
118 118
119 return str_replace('+', '', $token); 119 return str_replace('+', '', $token);
120 } 120 }
121
122 /**
123 * For a given text, we calculate reading time for an article.
124 *
125 * @param $text
126 *
127 * @return float
128 */
129 public static function getReadingTime($text)
130 {
131 return floor(str_word_count(strip_tags($text)) / 200);
132 }
121} 133}
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
index a4514d9e..f885ee94 100644
--- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
@@ -13,20 +13,15 @@ class EntryRepository extends EntityRepository
13 * 13 *
14 * @param int $userId 14 * @param int $userId
15 * 15 *
16 * @return Pagerfanta 16 * @return QueryBuilder
17 */ 17 */
18 public function findUnreadByUser($userId) 18 public function findUnreadByUser($userId)
19 { 19 {
20 $qb = $this->createQueryBuilder('e') 20 return $this->createQueryBuilder('e')
21 ->leftJoin('e.user', 'u') 21 ->leftJoin('e.user', 'u')
22 ->where('e.isArchived = false') 22 ->where('e.isArchived = false')
23 ->andWhere('u.id =:userId')->setParameter('userId', $userId) 23 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
24 ->orderBy('e.id', 'desc') 24 ->orderBy('e.id', 'desc');
25 ->getQuery();
26
27 $pagerAdapter = new DoctrineORMAdapter($qb);
28
29 return new Pagerfanta($pagerAdapter);
30 } 25 }
31 26
32 /** 27 /**
@@ -34,21 +29,15 @@ class EntryRepository extends EntityRepository
34 * 29 *
35 * @param int $userId 30 * @param int $userId
36 * 31 *
37 * @return Pagerfanta 32 * @return QueryBuilder
38 */ 33 */
39 public function findArchiveByUser($userId) 34 public function findArchiveByUser($userId)
40 { 35 {
41 $qb = $this->createQueryBuilder('e') 36 return $this->createQueryBuilder('e')
42 ->select('e')
43 ->leftJoin('e.user', 'u') 37 ->leftJoin('e.user', 'u')
44 ->where('e.isArchived = true') 38 ->where('e.isArchived = true')
45 ->andWhere('u.id =:userId')->setParameter('userId', $userId) 39 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
46 ->orderBy('e.id', 'desc') 40 ->orderBy('e.id', 'desc');
47 ->getQuery();
48
49 $pagerAdapter = new DoctrineORMAdapter($qb);
50
51 return new Pagerfanta($pagerAdapter);
52 } 41 }
53 42
54 /** 43 /**
@@ -56,22 +45,15 @@ class EntryRepository extends EntityRepository
56 * 45 *
57 * @param int $userId 46 * @param int $userId
58 * 47 *
59 * @return Pagerfanta 48 * @return QueryBuilder
60 */ 49 */
61 public function findStarredByUser($userId) 50 public function findStarredByUser($userId)
62 { 51 {
63 52 return $this->createQueryBuilder('e')
64 $qb = $this->createQueryBuilder('e')
65 ->select('e')
66 ->leftJoin('e.user', 'u') 53 ->leftJoin('e.user', 'u')
67 ->where('e.isStarred = true') 54 ->where('e.isStarred = true')
68 ->andWhere('u.id =:userId')->setParameter('userId', $userId) 55 ->andWhere('u.id =:userId')->setParameter('userId', $userId)
69 ->orderBy('e.id', 'desc') 56 ->orderBy('e.id', 'desc');
70 ->getQuery();
71
72 $pagerAdapter = new DoctrineORMAdapter($qb);
73
74 return new Pagerfanta($pagerAdapter);
75 } 57 }
76 58
77 /** 59 /**
diff --git a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig
index bf3caf09..7629ef35 100644
--- a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.html.twig
@@ -21,11 +21,12 @@
21 {% if entries is empty %} 21 {% if entries is empty %}
22 <div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div> 22 <div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div>
23 {% else %} 23 {% else %}
24 <div><form>{{ form_rest(form) }}<button class="btn waves-effect waves-light" type="submit" id="submit-filter" value="filter">Filter</button></form></div>
24 {% for entry in entries %} 25 {% for entry in entries %}
25 <div id="entry-{{ entry.id|e }}" class="entrie"> 26 <div id="entry-{{ entry.id|e }}" class="entry">
26 <h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2> 27 <h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2>
27 {% if entry.content| readingTime > 0 %} 28 {% if entry.readingTime > 0 %}
28 <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.content| readingTime }} min</span></div> 29 <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min</span></div>
29 {% else %} 30 {% else %}
30 <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div> 31 <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div>
31 {% endif %} 32 {% endif %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig
index 5ec9bc03..a39a8dc3 100644
--- a/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/Entry/entries.xml.twig
@@ -17,8 +17,8 @@
17 <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate> 17 <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate>
18 <description> 18 <description>
19 <![CDATA[ 19 <![CDATA[
20 {%- if entry.content|readingTime > 0 -%} 20 {%- if entry.readingTime > 0 -%}
21 {% trans %}estimated reading time :{% endtrans %} {{ entry.content|readingTime }} min 21 {% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min
22 {%- else -%} 22 {%- else -%}
23 {% trans %}estimated reading time :{% endtrans %} &lt; 1 min 23 {% trans %}estimated reading time :{% endtrans %} &lt; 1 min
24 {%- endif %} 24 {%- endif %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css b/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css
index e3069b86..ffd9d022 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/_global/public/css/style.css
@@ -121,7 +121,7 @@ a:visited {
121 font-size: 1.3em; 121 font-size: 1.3em;
122} 122}
123 123
124#main #content .entrie { 124#main #content .entry {
125 margin-top: 15px; 125 margin-top: 15px;
126 padding-bottom: 15px; 126 padding-bottom: 15px;
127 border-bottom: 1px dashed #222; 127 border-bottom: 1px dashed #222;
@@ -129,19 +129,19 @@ a:visited {
129} 129}
130 130
131/* First entry */ 131/* First entry */
132#main #content .results + .entrie { 132#main #content .results + .entry {
133 clear: both; 133 clear: both;
134 margin-top: 0; 134 margin-top: 0;
135} 135}
136 136
137#main .entrie .tools { 137#main .entry .tools {
138 float: right; 138 float: right;
139 text-align: right; 139 text-align: right;
140 list-style-type: none; 140 list-style-type: none;
141 opacity: 0.5; 141 opacity: 0.5;
142} 142}
143 143
144#main .entrie .tools .tool span { 144#main .entry .tools .tool span {
145 display: inline-block; 145 display: inline-block;
146 width: 16px; 146 width: 16px;
147 height: 16px; 147 height: 16px;
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css
index e2844ccc..6090face 100755
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/public/css/main.css
@@ -322,7 +322,7 @@ footer a {
322 letter-spacing:-5px; 322 letter-spacing:-5px;
323} 323}
324 324
325.listmode .entrie { 325.listmode .entry {
326 width: 100%!important; 326 width: 100%!important;
327 margin-left: 0!important; 327 margin-left: 0!important;
328} 328}
@@ -343,7 +343,7 @@ footer a {
343 top: -1px; 343 top: -1px;
344} 344}
345 345
346.entrie { 346.entry {
347 background-color: #FFF; 347 background-color: #FFF;
348 letter-spacing:normal; 348 letter-spacing:normal;
349 box-shadow: 0 3px 7px rgba(0,0,0,0.3); 349 box-shadow: 0 3px 7px rgba(0,0,0,0.3);
@@ -366,7 +366,7 @@ footer a {
366 /* transition: all 0.5s ease; */ 366 /* transition: all 0.5s ease; */
367} 367}
368 368
369.entrie:before { 369.entry:before {
370 content: ""; 370 content: "";
371 width: 0; 371 width: 0;
372 height: 0; 372 height: 0;
@@ -384,7 +384,7 @@ footer a {
384 transition: all 0.5s ease; 384 transition: all 0.5s ease;
385} 385}
386 386
387.entrie:after { 387.entry:after {
388 content: ""; 388 content: "";
389 position: absolute; 389 position: absolute;
390 height: 7px; 390 height: 7px;
@@ -399,34 +399,34 @@ footer a {
399 transition: all 0.5s ease; 399 transition: all 0.5s ease;
400} 400}
401 401
402.entrie:hover { 402.entry:hover {
403 box-shadow: 0 3px 10px rgba(0,0,0,1); 403 box-shadow: 0 3px 10px rgba(0,0,0,1);
404} 404}
405 405
406.entrie:hover:after { 406.entry:hover:after {
407 height: 40px; 407 height: 40px;
408} 408}
409 409
410.entrie:hover:before { 410.entry:hover:before {
411 bottom: 2.4em; 411 bottom: 2.4em;
412} 412}
413 413
414.entrie:hover h2 a { 414.entry:hover h2 a {
415 color: #666; 415 color: #666;
416} 416}
417 417
418.entrie h2 { 418.entry h2 {
419 text-transform: none; 419 text-transform: none;
420 margin-bottom: 0; 420 margin-bottom: 0;
421 line-height: 1.2; 421 line-height: 1.2;
422} 422}
423 423
424 .entrie h2:after { 424 .entry h2:after {
425 content: none; 425 content: none;
426 } 426 }
427 427
428 428
429.entrie h2 a { 429.entry h2 a {
430 display: block; 430 display: block;
431 text-decoration: none; 431 text-decoration: none;
432 color: #000; 432 color: #000;
@@ -438,7 +438,7 @@ footer a {
438 transition: all 0.5s ease; 438 transition: all 0.5s ease;
439} 439}
440/* 440/*
441.entrie h2 a:after { 441.entry h2 a:after {
442 content: ""; 442 content: "";
443 position: absolute; 443 position: absolute;
444 top: 0; 444 top: 0;
@@ -448,21 +448,21 @@ footer a {
448} 448}
449*/ 449*/
450 450
451.entrie p { 451.entry p {
452 color: #666; 452 color: #666;
453 font-size: 0.9em; 453 font-size: 0.9em;
454 line-height: 1.7; 454 line-height: 1.7;
455} 455}
456 456
457 .entrie h2 a:first-letter { 457 .entry h2 a:first-letter {
458 text-transform: uppercase; 458 text-transform: uppercase;
459 } 459 }
460 460
461.entrie:hover .tools { 461.entry:hover .tools {
462 bottom: 0; 462 bottom: 0;
463} 463}
464 464
465.entrie .tools { 465.entry .tools {
466 position: absolute; 466 position: absolute;
467 bottom: -50px; 467 bottom: -50px;
468 left: 0; 468 left: 0;
@@ -477,22 +477,22 @@ footer a {
477 transition: all 0.5s ease; 477 transition: all 0.5s ease;
478} 478}
479 479
480 .entrie .tools a { 480 .entry .tools a {
481 color: #666; 481 color: #666;
482 text-decoration: none; 482 text-decoration: none;
483 display: block; 483 display: block;
484 padding: 0.4em; 484 padding: 0.4em;
485 } 485 }
486 486
487 .entrie .tools a:hover { 487 .entry .tools a:hover {
488 color: #FFF; 488 color: #FFF;
489 } 489 }
490 490
491 .entrie .tools li { 491 .entry .tools li {
492 display: inline-block; 492 display: inline-block;
493 } 493 }
494 494
495.entrie:nth-child(3n+1) { 495.entry:nth-child(3n+1) {
496 margin-left: 0; 496 margin-left: 0;
497} 497}
498 498
@@ -941,13 +941,13 @@ pre code {
941 ========================================================================== */ 941 ========================================================================== */
942 942
943@media screen and (max-width: 1050px) { 943@media screen and (max-width: 1050px) {
944 .entrie { 944 .entry {
945 width: 49%; 945 width: 49%;
946 } 946 }
947 .entrie:nth-child(3n+1) { 947 .entry:nth-child(3n+1) {
948 margin-left: 1.5%; 948 margin-left: 1.5%;
949 } 949 }
950 .entrie:nth-child(2n+1) { 950 .entry:nth-child(2n+1) {
951 margin-left: 0; 951 margin-left: 0;
952 } 952 }
953} 953}
@@ -962,7 +962,7 @@ pre code {
962} 962}
963 963
964@media screen and (max-width: 700px) { 964@media screen and (max-width: 700px) {
965 .entrie { 965 .entry {
966 width: 100%; 966 width: 100%;
967 margin-left: 0; 967 margin-left: 0;
968 } 968 }
@@ -972,7 +972,7 @@ pre code {
972} 972}
973 973
974@media screen and (max-width: 500px) { 974@media screen and (max-width: 500px) {
975 .entrie { 975 .entry {
976 width: 100%; 976 width: 100%;
977 margin-left: 0; 977 margin-left: 0;
978 } 978 }
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
index fbdc1ffd..b9f1be49 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
@@ -18,6 +18,7 @@
18 {% if entries is not empty %} 18 {% if entries is not empty %}
19 <div class="results clearfix"> 19 <div class="results clearfix">
20 <div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div> 20 <div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div>
21 <div class="left"><form>{{ form_rest(form) }}<button class="btn waves-effect waves-light" type="submit" id="submit-filter" value="filter">Filter</button></form></div>
21 <ul class="pagination right"> 22 <ul class="pagination right">
22 {% for p in range(1, entries.nbPages) %} 23 {% for p in range(1, entries.nbPages) %}
23 <li class="{{ currentPage == p ? 'active':'waves-effect'}}"> 24 <li class="{{ currentPage == p ? 'active':'waves-effect'}}">
@@ -38,8 +39,8 @@
38 <div class="card"> 39 <div class="card">
39 <div class="card-content"> 40 <div class="card-content">
40 <span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span> 41 <span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span>
41 {% if entry.content| readingTime > 0 %} 42 {% if entry.readingTime > 0 %}
42 <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.content| readingTime }} min</span></div> 43 <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.readingTime }} min</span></div>
43 {% else %} 44 {% else %}
44 <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div> 45 <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div>
45 {% endif %} 46 {% endif %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css
index 9dd6d295..2a799c44 100755
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/css/print.css
@@ -25,7 +25,7 @@ body > footer,
25div.tools, 25div.tools,
26header div, 26header div,
27.messages, 27.messages,
28.entrie + .results { 28.entry + .results {
29 display: none !important; 29 display: none !important;
30} 30}
31 31
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
index 2cd50130..24848eb2 100644
--- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
+++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php
@@ -240,4 +240,23 @@ class EntryControllerTest extends WallabagCoreTestCase
240 240
241 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 241 $this->assertEquals(403, $client->getResponse()->getStatusCode());
242 } 242 }
243
244 public function testFilterOnUnreadeView()
245 {
246 $this->logInAs('admin');
247 $client = $this->getClient();
248
249 $crawler = $client->request('GET', '/unread/list');
250
251 $form = $crawler->filter('button[id=submit-filter]')->form();
252
253 $data = array(
254 'entry_filter[readingTime][right_number]' => 11,
255 'entry_filter[readingTime][left_number]' => 11
256 );
257
258 $crawler = $client->submit($form, $data);
259
260 $this->assertCount(1, $crawler->filter('div[class=entry]'));
261 }
243} 262}
diff --git a/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php b/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php
index 18388948..5f0a9643 100644
--- a/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php
+++ b/src/Wallabag/CoreBundle/Twig/Extension/WallabagExtension.php
@@ -7,7 +7,6 @@ class WallabagExtension extends \Twig_Extension
7 public function getFilters() 7 public function getFilters()
8 { 8 {
9 return array( 9 return array(
10 new \Twig_SimpleFilter('readingTime', array($this, 'getReadingTime')),
11 new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')), 10 new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')),
12 ); 11 );
13 } 12 }
@@ -24,18 +23,6 @@ class WallabagExtension extends \Twig_Extension
24 return parse_url($url, PHP_URL_HOST); 23 return parse_url($url, PHP_URL_HOST);
25 } 24 }
26 25
27 /**
28 * For a given text, we calculate reading time for an article.
29 *
30 * @param $text
31 *
32 * @return float
33 */
34 public static function getReadingTime($text)
35 {
36 return floor(str_word_count(strip_tags($text)) / 200);
37 }
38
39 public function getName() 26 public function getName()
40 { 27 {
41 return 'wallabag_extension'; 28 return 'wallabag_extension';