store estimated reading time / filters on reading time

This commit is contained in:
Nicolas Lœuillet 2015-08-07 22:20:30 +02:00
parent fedaf00537
commit 2686457448
20 changed files with 433 additions and 279 deletions

View file

@ -25,6 +25,7 @@ class AppKernel extends Kernel
new Wallabag\CoreBundle\WallabagCoreBundle(), new Wallabag\CoreBundle\WallabagCoreBundle(),
new Wallabag\ApiBundle\WallabagApiBundle(), new Wallabag\ApiBundle\WallabagApiBundle(),
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
); );
if (in_array($this->getEnvironment(), array('dev', 'test'))) { if (in_array($this->getEnvironment(), array('dev', 'test'))) {

View file

@ -638,7 +638,7 @@ class SymfonyRequirements extends RequirementCollection
} }
$this->addRecommendation( $this->addRecommendation(
class_exists('Locale'), extension_loaded('intl'),
'intl extension should be available', 'intl extension should be available',
'Install and enable the <strong>intl</strong> extension (used for validators).' 'Install and enable the <strong>intl</strong> extension (used for validators).'
); );

View file

@ -42,9 +42,9 @@ foreach ($symfonyRequirements->getRecommendations() as $req) {
} }
if ($checkPassed) { if ($checkPassed) {
echo_block('success', 'OK', 'Your system is ready to run Symfony2 projects', true); echo_block('success', 'OK', 'Your system is ready to run Symfony2 projects');
} else { } else {
echo_block('error', 'ERROR', 'Your system is not ready to run Symfony2 projects', true); echo_block('error', 'ERROR', 'Your system is not ready to run Symfony2 projects');
echo_title('Fix the following mandatory requirements', 'red'); echo_title('Fix the following mandatory requirements', 'red');

View file

@ -47,7 +47,9 @@ twig:
version: %app.version% version: %app.version%
paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb" paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
flattr_url: "https://flattr.com/thing/1265480" flattr_url: "https://flattr.com/thing/1265480"
form:
resources:
- LexikFormFilterBundle:Form:form_div_layout.html.twig
# Assetic Configuration # Assetic Configuration
assetic: assetic:
debug: "%kernel.debug%" debug: "%kernel.debug%"

View file

@ -83,7 +83,8 @@
"wallabag/php-readability": "dev-master", "wallabag/php-readability": "dev-master",
"wallabag/phpMobi": "dev-master", "wallabag/phpMobi": "dev-master",
"wallabag/Fivefilters_Libraries": "dev-master", "wallabag/Fivefilters_Libraries": "dev-master",
"pagerfanta/pagerfanta": "~1.0.3" "pagerfanta/pagerfanta": "~1.0.3",
"lexik/form-filter-bundle": "~4.0"
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "~2.2.0", "doctrine/doctrine-fixtures-bundle": "~2.2.0",

427
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,9 @@ use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Service\Extractor; use Wallabag\CoreBundle\Service\Extractor;
use Wallabag\CoreBundle\Form\Type\NewEntryType; use Wallabag\CoreBundle\Form\Type\NewEntryType;
use Wallabag\CoreBundle\Form\Type\EditEntryType; use Wallabag\CoreBundle\Form\Type\EditEntryType;
use Wallabag\CoreBundle\Filter\EntryFilterType;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
class EntryController extends Controller class EntryController extends Controller
{ {
@ -89,22 +92,39 @@ class EntryController extends Controller
/** /**
* Shows unread entries for current user. * Shows unread entries for current user.
* *
* @param Request $request
* @param int $page
*
* @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"}) * @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"})
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function showUnreadAction($page) public function showUnreadAction(Request $request, $page)
{ {
$entries = $this->getDoctrine() $form = $this->get('form.factory')->create(new EntryFilterType());
$filterBuilder = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findUnreadByUser($this->getUser()->getId()); ->findUnreadByUser($this->getUser()->getId());
if ($request->query->has($form->getName())) {
// manually bind values from the request
$form->submit($request->query->get($form->getName()));
// build the query from the given form object
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
}
$pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
return $this->render( return $this->render(
'WallabagCoreBundle:Entry:entries.html.twig', 'WallabagCoreBundle:Entry:entries.html.twig',
array( array(
'form' => $form->createView(),
'entries' => $entries, 'entries' => $entries,
'currentPage' => $page 'currentPage' => $page
) )
@ -114,22 +134,39 @@ class EntryController extends Controller
/** /**
* Shows read entries for current user. * Shows read entries for current user.
* *
* @param Request $request
* @param int $page
*
* @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"}) * @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"})
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function showArchiveAction($page) public function showArchiveAction(Request $request, $page)
{ {
$entries = $this->getDoctrine() $form = $this->get('form.factory')->create(new EntryFilterType());
$filterBuilder = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findArchiveByUser($this->getUser()->getId()); ->findArchiveByUser($this->getUser()->getId());
if ($request->query->has($form->getName())) {
// manually bind values from the request
$form->submit($request->query->get($form->getName()));
// build the query from the given form object
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
}
$pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
return $this->render( return $this->render(
'WallabagCoreBundle:Entry:entries.html.twig', 'WallabagCoreBundle:Entry:entries.html.twig',
array( array(
'form' => $form->createView(),
'entries' => $entries, 'entries' => $entries,
'currentPage' => $page 'currentPage' => $page
) )
@ -139,22 +176,39 @@ class EntryController extends Controller
/** /**
* Shows starred entries for current user. * Shows starred entries for current user.
* *
* @param Request $request
* @param int $page
*
* @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"}) * @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function showStarredAction($page) public function showStarredAction(Request $request, $page)
{ {
$entries = $this->getDoctrine() $form = $this->get('form.factory')->create(new EntryFilterType());
$filterBuilder = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findStarredByUser($this->getUser()->getId()); ->findStarredByUser($this->getUser()->getId());
if ($request->query->has($form->getName())) {
// manually bind values from the request
$form->submit($request->query->get($form->getName()));
// build the query from the given form object
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);
}
$pagerAdapter = new DoctrineORMAdapter($filterBuilder->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage()); $entries->setMaxPerPage($this->getUser()->getConfig()->getItemsPerPage());
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
return $this->render( return $this->render(
'WallabagCoreBundle:Entry:entries.html.twig', 'WallabagCoreBundle:Entry:entries.html.twig',
array( array(
'form' => $form->createView(),
'entries' => $entries, 'entries' => $entries,
'currentPage' => $page 'currentPage' => $page
) )

View file

@ -7,6 +7,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Wallabag\CoreBundle\Entity\User; use Wallabag\CoreBundle\Entity\User;
use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Entry;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
class RssController extends Controller class RssController extends Controller
{ {
@ -20,12 +22,15 @@ class RssController extends Controller
*/ */
public function showUnreadAction(User $user) public function showUnreadAction(User $user)
{ {
$entries = $this->getDoctrine() $qb = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findUnreadByUser( ->findUnreadByUser(
$user->getId() $user->getId()
); );
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
$entries->setMaxPerPage($perPage); $entries->setMaxPerPage($perPage);
@ -45,12 +50,15 @@ class RssController extends Controller
*/ */
public function showArchiveAction(User $user) public function showArchiveAction(User $user)
{ {
$entries = $this->getDoctrine() $qb = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findArchiveByUser( ->findArchiveByUser(
$user->getId() $user->getId()
); );
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
$entries->setMaxPerPage($perPage); $entries->setMaxPerPage($perPage);
@ -70,12 +78,15 @@ class RssController extends Controller
*/ */
public function showStarredAction(User $user) public function showStarredAction(User $user)
{ {
$entries = $this->getDoctrine() $qb = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findStarredByUser( ->findStarredByUser(
$user->getId() $user->getId()
); );
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
$entries = new Pagerfanta($pagerAdapter);
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit'); $perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
$entries->setMaxPerPage($perPage); $entries->setMaxPerPage($perPage);

View file

@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
use Hateoas\Configuration\Annotation as Hateoas; use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\XmlRoot; use JMS\Serializer\Annotation\XmlRoot;
use Wallabag\CoreBundle\Helper\Tools;
/** /**
* Entry. * Entry.
@ -96,7 +97,7 @@ class Entry
/** /**
* @var int * @var int
* *
* @ORM\Column(name="reading_type", type="integer", nullable=true) * @ORM\Column(name="reading_time", type="integer", nullable=true)
*/ */
private $readingTime; private $readingTime;
@ -264,6 +265,7 @@ class Entry
public function setContent($content) public function setContent($content)
{ {
$this->content = $content; $this->content = $content;
$this->readingTime = Tools::getReadingTime($content);
return $this; return $this;
} }

View file

@ -0,0 +1,28 @@
<?php
namespace Wallabag\CoreBundle\Filter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class EntryFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('readingTime', 'filter_number_range');
}
public function getName()
{
return 'entry_filter';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false,
'validation_groups' => array('filtering')
));
}
}

View file

@ -118,4 +118,16 @@ final class Tools
return str_replace('+', '', $token); return str_replace('+', '', $token);
} }
/**
* For a given text, we calculate reading time for an article.
*
* @param $text
*
* @return float
*/
public static function getReadingTime($text)
{
return floor(str_word_count(strip_tags($text)) / 200);
}
} }

View file

@ -13,20 +13,15 @@ class EntryRepository extends EntityRepository
* *
* @param int $userId * @param int $userId
* *
* @return Pagerfanta * @return QueryBuilder
*/ */
public function findUnreadByUser($userId) public function findUnreadByUser($userId)
{ {
$qb = $this->createQueryBuilder('e') return $this->createQueryBuilder('e')
->leftJoin('e.user', 'u') ->leftJoin('e.user', 'u')
->where('e.isArchived = false') ->where('e.isArchived = false')
->andWhere('u.id =:userId')->setParameter('userId', $userId) ->andWhere('u.id =:userId')->setParameter('userId', $userId)
->orderBy('e.id', 'desc') ->orderBy('e.id', 'desc');
->getQuery();
$pagerAdapter = new DoctrineORMAdapter($qb);
return new Pagerfanta($pagerAdapter);
} }
/** /**
@ -34,21 +29,15 @@ class EntryRepository extends EntityRepository
* *
* @param int $userId * @param int $userId
* *
* @return Pagerfanta * @return QueryBuilder
*/ */
public function findArchiveByUser($userId) public function findArchiveByUser($userId)
{ {
$qb = $this->createQueryBuilder('e') return $this->createQueryBuilder('e')
->select('e')
->leftJoin('e.user', 'u') ->leftJoin('e.user', 'u')
->where('e.isArchived = true') ->where('e.isArchived = true')
->andWhere('u.id =:userId')->setParameter('userId', $userId) ->andWhere('u.id =:userId')->setParameter('userId', $userId)
->orderBy('e.id', 'desc') ->orderBy('e.id', 'desc');
->getQuery();
$pagerAdapter = new DoctrineORMAdapter($qb);
return new Pagerfanta($pagerAdapter);
} }
/** /**
@ -56,22 +45,15 @@ class EntryRepository extends EntityRepository
* *
* @param int $userId * @param int $userId
* *
* @return Pagerfanta * @return QueryBuilder
*/ */
public function findStarredByUser($userId) public function findStarredByUser($userId)
{ {
return $this->createQueryBuilder('e')
$qb = $this->createQueryBuilder('e')
->select('e')
->leftJoin('e.user', 'u') ->leftJoin('e.user', 'u')
->where('e.isStarred = true') ->where('e.isStarred = true')
->andWhere('u.id =:userId')->setParameter('userId', $userId) ->andWhere('u.id =:userId')->setParameter('userId', $userId)
->orderBy('e.id', 'desc') ->orderBy('e.id', 'desc');
->getQuery();
$pagerAdapter = new DoctrineORMAdapter($qb);
return new Pagerfanta($pagerAdapter);
} }
/** /**

View file

@ -21,11 +21,12 @@
{% if entries is empty %} {% if entries is empty %}
<div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div> <div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div>
{% else %} {% else %}
<div><form>{{ form_rest(form) }}<button class="btn waves-effect waves-light" type="submit" id="submit-filter" value="filter">Filter</button></form></div>
{% for entry in entries %} {% for entry in entries %}
<div id="entry-{{ entry.id|e }}" class="entrie"> <div id="entry-{{ entry.id|e }}" class="entry">
<h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2> <h2><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></h2>
{% if entry.content| readingTime > 0 %} {% if entry.readingTime > 0 %}
<div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.content| readingTime }} min</span></div> <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min</span></div>
{% else %} {% else %}
<div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div> <div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div>
{% endif %} {% endif %}

View file

@ -17,8 +17,8 @@
<pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate> <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate>
<description> <description>
<![CDATA[ <![CDATA[
{%- if entry.content|readingTime > 0 -%} {%- if entry.readingTime > 0 -%}
{% trans %}estimated reading time :{% endtrans %} {{ entry.content|readingTime }} min {% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min
{%- else -%} {%- else -%}
{% trans %}estimated reading time :{% endtrans %} &lt; 1 min {% trans %}estimated reading time :{% endtrans %} &lt; 1 min
{%- endif %} {%- endif %}

View file

@ -121,7 +121,7 @@ a:visited {
font-size: 1.3em; font-size: 1.3em;
} }
#main #content .entrie { #main #content .entry {
margin-top: 15px; margin-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
border-bottom: 1px dashed #222; border-bottom: 1px dashed #222;
@ -129,19 +129,19 @@ a:visited {
} }
/* First entry */ /* First entry */
#main #content .results + .entrie { #main #content .results + .entry {
clear: both; clear: both;
margin-top: 0; margin-top: 0;
} }
#main .entrie .tools { #main .entry .tools {
float: right; float: right;
text-align: right; text-align: right;
list-style-type: none; list-style-type: none;
opacity: 0.5; opacity: 0.5;
} }
#main .entrie .tools .tool span { #main .entry .tools .tool span {
display: inline-block; display: inline-block;
width: 16px; width: 16px;
height: 16px; height: 16px;

View file

@ -322,7 +322,7 @@ footer a {
letter-spacing:-5px; letter-spacing:-5px;
} }
.listmode .entrie { .listmode .entry {
width: 100%!important; width: 100%!important;
margin-left: 0!important; margin-left: 0!important;
} }
@ -343,7 +343,7 @@ footer a {
top: -1px; top: -1px;
} }
.entrie { .entry {
background-color: #FFF; background-color: #FFF;
letter-spacing:normal; letter-spacing:normal;
box-shadow: 0 3px 7px rgba(0,0,0,0.3); box-shadow: 0 3px 7px rgba(0,0,0,0.3);
@ -366,7 +366,7 @@ footer a {
/* transition: all 0.5s ease; */ /* transition: all 0.5s ease; */
} }
.entrie:before { .entry:before {
content: ""; content: "";
width: 0; width: 0;
height: 0; height: 0;
@ -384,7 +384,7 @@ footer a {
transition: all 0.5s ease; transition: all 0.5s ease;
} }
.entrie:after { .entry:after {
content: ""; content: "";
position: absolute; position: absolute;
height: 7px; height: 7px;
@ -399,34 +399,34 @@ footer a {
transition: all 0.5s ease; transition: all 0.5s ease;
} }
.entrie:hover { .entry:hover {
box-shadow: 0 3px 10px rgba(0,0,0,1); box-shadow: 0 3px 10px rgba(0,0,0,1);
} }
.entrie:hover:after { .entry:hover:after {
height: 40px; height: 40px;
} }
.entrie:hover:before { .entry:hover:before {
bottom: 2.4em; bottom: 2.4em;
} }
.entrie:hover h2 a { .entry:hover h2 a {
color: #666; color: #666;
} }
.entrie h2 { .entry h2 {
text-transform: none; text-transform: none;
margin-bottom: 0; margin-bottom: 0;
line-height: 1.2; line-height: 1.2;
} }
.entrie h2:after { .entry h2:after {
content: none; content: none;
} }
.entrie h2 a { .entry h2 a {
display: block; display: block;
text-decoration: none; text-decoration: none;
color: #000; color: #000;
@ -438,7 +438,7 @@ footer a {
transition: all 0.5s ease; transition: all 0.5s ease;
} }
/* /*
.entrie h2 a:after { .entry h2 a:after {
content: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
@ -448,21 +448,21 @@ footer a {
} }
*/ */
.entrie p { .entry p {
color: #666; color: #666;
font-size: 0.9em; font-size: 0.9em;
line-height: 1.7; line-height: 1.7;
} }
.entrie h2 a:first-letter { .entry h2 a:first-letter {
text-transform: uppercase; text-transform: uppercase;
} }
.entrie:hover .tools { .entry:hover .tools {
bottom: 0; bottom: 0;
} }
.entrie .tools { .entry .tools {
position: absolute; position: absolute;
bottom: -50px; bottom: -50px;
left: 0; left: 0;
@ -477,22 +477,22 @@ footer a {
transition: all 0.5s ease; transition: all 0.5s ease;
} }
.entrie .tools a { .entry .tools a {
color: #666; color: #666;
text-decoration: none; text-decoration: none;
display: block; display: block;
padding: 0.4em; padding: 0.4em;
} }
.entrie .tools a:hover { .entry .tools a:hover {
color: #FFF; color: #FFF;
} }
.entrie .tools li { .entry .tools li {
display: inline-block; display: inline-block;
} }
.entrie:nth-child(3n+1) { .entry:nth-child(3n+1) {
margin-left: 0; margin-left: 0;
} }
@ -941,13 +941,13 @@ pre code {
========================================================================== */ ========================================================================== */
@media screen and (max-width: 1050px) { @media screen and (max-width: 1050px) {
.entrie { .entry {
width: 49%; width: 49%;
} }
.entrie:nth-child(3n+1) { .entry:nth-child(3n+1) {
margin-left: 1.5%; margin-left: 1.5%;
} }
.entrie:nth-child(2n+1) { .entry:nth-child(2n+1) {
margin-left: 0; margin-left: 0;
} }
} }
@ -962,7 +962,7 @@ pre code {
} }
@media screen and (max-width: 700px) { @media screen and (max-width: 700px) {
.entrie { .entry {
width: 100%; width: 100%;
margin-left: 0; margin-left: 0;
} }
@ -972,7 +972,7 @@ pre code {
} }
@media screen and (max-width: 500px) { @media screen and (max-width: 500px) {
.entrie { .entry {
width: 100%; width: 100%;
margin-left: 0; margin-left: 0;
} }

View file

@ -18,6 +18,7 @@
{% if entries is not empty %} {% if entries is not empty %}
<div class="results clearfix"> <div class="results clearfix">
<div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div> <div class="nb-results left">{{ entries.count }} {% trans %}entries{% endtrans %}</div>
<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>
<ul class="pagination right"> <ul class="pagination right">
{% for p in range(1, entries.nbPages) %} {% for p in range(1, entries.nbPages) %}
<li class="{{ currentPage == p ? 'active':'waves-effect'}}"> <li class="{{ currentPage == p ? 'active':'waves-effect'}}">
@ -38,8 +39,8 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span> <span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span>
{% if entry.content| readingTime > 0 %} {% if entry.readingTime > 0 %}
<div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.content| readingTime }} min</span></div> <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.readingTime }} min</span></div>
{% else %} {% else %}
<div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div> <div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur">&lt;</small> 1 min</span></div>
{% endif %} {% endif %}

View file

@ -25,7 +25,7 @@ body > footer,
div.tools, div.tools,
header div, header div,
.messages, .messages,
.entrie + .results { .entry + .results {
display: none !important; display: none !important;
} }

View file

@ -240,4 +240,23 @@ class EntryControllerTest extends WallabagCoreTestCase
$this->assertEquals(403, $client->getResponse()->getStatusCode()); $this->assertEquals(403, $client->getResponse()->getStatusCode());
} }
public function testFilterOnUnreadeView()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/unread/list');
$form = $crawler->filter('button[id=submit-filter]')->form();
$data = array(
'entry_filter[readingTime][right_number]' => 11,
'entry_filter[readingTime][left_number]' => 11
);
$crawler = $client->submit($form, $data);
$this->assertCount(1, $crawler->filter('div[class=entry]'));
}
} }

View file

@ -7,7 +7,6 @@ class WallabagExtension extends \Twig_Extension
public function getFilters() public function getFilters()
{ {
return array( return array(
new \Twig_SimpleFilter('readingTime', array($this, 'getReadingTime')),
new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')), new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')),
); );
} }
@ -24,18 +23,6 @@ class WallabagExtension extends \Twig_Extension
return parse_url($url, PHP_URL_HOST); return parse_url($url, PHP_URL_HOST);
} }
/**
* For a given text, we calculate reading time for an article.
*
* @param $text
*
* @return float
*/
public static function getReadingTime($text)
{
return floor(str_word_count(strip_tags($text)) / 200);
}
public function getName() public function getName()
{ {
return 'wallabag_extension'; return 'wallabag_extension';