mirror of
https://github.com/wallabag/wallabag.git
synced 2024-12-27 10:00:29 +00:00
store estimated reading time / filters on reading time
This commit is contained in:
parent
fedaf00537
commit
2686457448
20 changed files with 433 additions and 279 deletions
|
@ -25,6 +25,7 @@ class AppKernel extends Kernel
|
|||
new Wallabag\CoreBundle\WallabagCoreBundle(),
|
||||
new Wallabag\ApiBundle\WallabagApiBundle(),
|
||||
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
|
||||
new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
|
||||
);
|
||||
|
||||
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
|
|
|
@ -638,7 +638,7 @@ class SymfonyRequirements extends RequirementCollection
|
|||
}
|
||||
|
||||
$this->addRecommendation(
|
||||
class_exists('Locale'),
|
||||
extension_loaded('intl'),
|
||||
'intl extension should be available',
|
||||
'Install and enable the <strong>intl</strong> extension (used for validators).'
|
||||
);
|
||||
|
|
|
@ -42,9 +42,9 @@ foreach ($symfonyRequirements->getRecommendations() as $req) {
|
|||
}
|
||||
|
||||
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 {
|
||||
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');
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ twig:
|
|||
version: %app.version%
|
||||
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"
|
||||
|
||||
form:
|
||||
resources:
|
||||
- LexikFormFilterBundle:Form:form_div_layout.html.twig
|
||||
# Assetic Configuration
|
||||
assetic:
|
||||
debug: "%kernel.debug%"
|
||||
|
|
|
@ -83,7 +83,8 @@
|
|||
"wallabag/php-readability": "dev-master",
|
||||
"wallabag/phpMobi": "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": {
|
||||
"doctrine/doctrine-fixtures-bundle": "~2.2.0",
|
||||
|
|
427
composer.lock
generated
427
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,9 @@ use Wallabag\CoreBundle\Entity\Entry;
|
|||
use Wallabag\CoreBundle\Service\Extractor;
|
||||
use Wallabag\CoreBundle\Form\Type\NewEntryType;
|
||||
use Wallabag\CoreBundle\Form\Type\EditEntryType;
|
||||
use Wallabag\CoreBundle\Filter\EntryFilterType;
|
||||
use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
|
||||
class EntryController extends Controller
|
||||
{
|
||||
|
@ -89,22 +92,39 @@ class EntryController extends Controller
|
|||
/**
|
||||
* Shows unread entries for current user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $page
|
||||
*
|
||||
* @Route("/unread/list/{page}", name="unread", defaults={"page" = "1"})
|
||||
*
|
||||
* @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')
|
||||
->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->setCurrentPage($page);
|
||||
|
||||
return $this->render(
|
||||
'WallabagCoreBundle:Entry:entries.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'entries' => $entries,
|
||||
'currentPage' => $page
|
||||
)
|
||||
|
@ -114,22 +134,39 @@ class EntryController extends Controller
|
|||
/**
|
||||
* Shows read entries for current user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $page
|
||||
*
|
||||
* @Route("/archive/list/{page}", name="archive", defaults={"page" = "1"})
|
||||
*
|
||||
* @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')
|
||||
->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->setCurrentPage($page);
|
||||
|
||||
return $this->render(
|
||||
'WallabagCoreBundle:Entry:entries.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'entries' => $entries,
|
||||
'currentPage' => $page
|
||||
)
|
||||
|
@ -139,22 +176,39 @@ class EntryController extends Controller
|
|||
/**
|
||||
* Shows starred entries for current user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $page
|
||||
*
|
||||
* @Route("/starred/list/{page}", name="starred", defaults={"page" = "1"})
|
||||
*
|
||||
* @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')
|
||||
->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->setCurrentPage($page);
|
||||
|
||||
return $this->render(
|
||||
'WallabagCoreBundle:Entry:entries.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'entries' => $entries,
|
||||
'currentPage' => $page
|
||||
)
|
||||
|
|
|
@ -7,6 +7,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
|||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Wallabag\CoreBundle\Entity\User;
|
||||
use Wallabag\CoreBundle\Entity\Entry;
|
||||
use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
|
||||
class RssController extends Controller
|
||||
{
|
||||
|
@ -20,12 +22,15 @@ class RssController extends Controller
|
|||
*/
|
||||
public function showUnreadAction(User $user)
|
||||
{
|
||||
$entries = $this->getDoctrine()
|
||||
$qb = $this->getDoctrine()
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findUnreadByUser(
|
||||
$user->getId()
|
||||
);
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
|
||||
$entries = new Pagerfanta($pagerAdapter);
|
||||
|
||||
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
|
||||
$entries->setMaxPerPage($perPage);
|
||||
|
||||
|
@ -45,12 +50,15 @@ class RssController extends Controller
|
|||
*/
|
||||
public function showArchiveAction(User $user)
|
||||
{
|
||||
$entries = $this->getDoctrine()
|
||||
$qb = $this->getDoctrine()
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findArchiveByUser(
|
||||
$user->getId()
|
||||
);
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
|
||||
$entries = new Pagerfanta($pagerAdapter);
|
||||
|
||||
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
|
||||
$entries->setMaxPerPage($perPage);
|
||||
|
||||
|
@ -70,12 +78,15 @@ class RssController extends Controller
|
|||
*/
|
||||
public function showStarredAction(User $user)
|
||||
{
|
||||
$entries = $this->getDoctrine()
|
||||
$qb = $this->getDoctrine()
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findStarredByUser(
|
||||
$user->getId()
|
||||
);
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
|
||||
$entries = new Pagerfanta($pagerAdapter);
|
||||
|
||||
$perPage = $user->getConfig()->getRssLimit() ?: $this->container->getParameter('rss_limit');
|
||||
$entries->setMaxPerPage($perPage);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation\XmlRoot;
|
||||
use Wallabag\CoreBundle\Helper\Tools;
|
||||
|
||||
/**
|
||||
* Entry.
|
||||
|
@ -96,7 +97,7 @@ class Entry
|
|||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="reading_type", type="integer", nullable=true)
|
||||
* @ORM\Column(name="reading_time", type="integer", nullable=true)
|
||||
*/
|
||||
private $readingTime;
|
||||
|
||||
|
@ -264,6 +265,7 @@ class Entry
|
|||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
$this->readingTime = Tools::getReadingTime($content);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
28
src/Wallabag/CoreBundle/Filter/EntryFilterType.php
Normal file
28
src/Wallabag/CoreBundle/Filter/EntryFilterType.php
Normal 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')
|
||||
));
|
||||
}
|
||||
}
|
|
@ -118,4 +118,16 @@ final class Tools
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,20 +13,15 @@ class EntryRepository extends EntityRepository
|
|||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return Pagerfanta
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function findUnreadByUser($userId)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('e')
|
||||
return $this->createQueryBuilder('e')
|
||||
->leftJoin('e.user', 'u')
|
||||
->where('e.isArchived = false')
|
||||
->andWhere('u.id =:userId')->setParameter('userId', $userId)
|
||||
->orderBy('e.id', 'desc')
|
||||
->getQuery();
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb);
|
||||
|
||||
return new Pagerfanta($pagerAdapter);
|
||||
->orderBy('e.id', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,21 +29,15 @@ class EntryRepository extends EntityRepository
|
|||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return Pagerfanta
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function findArchiveByUser($userId)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('e')
|
||||
->select('e')
|
||||
return $this->createQueryBuilder('e')
|
||||
->leftJoin('e.user', 'u')
|
||||
->where('e.isArchived = true')
|
||||
->andWhere('u.id =:userId')->setParameter('userId', $userId)
|
||||
->orderBy('e.id', 'desc')
|
||||
->getQuery();
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb);
|
||||
|
||||
return new Pagerfanta($pagerAdapter);
|
||||
->orderBy('e.id', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,22 +45,15 @@ class EntryRepository extends EntityRepository
|
|||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return Pagerfanta
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function findStarredByUser($userId)
|
||||
{
|
||||
|
||||
$qb = $this->createQueryBuilder('e')
|
||||
->select('e')
|
||||
return $this->createQueryBuilder('e')
|
||||
->leftJoin('e.user', 'u')
|
||||
->where('e.isStarred = true')
|
||||
->andWhere('u.id =:userId')->setParameter('userId', $userId)
|
||||
->orderBy('e.id', 'desc')
|
||||
->getQuery();
|
||||
|
||||
$pagerAdapter = new DoctrineORMAdapter($qb);
|
||||
|
||||
return new Pagerfanta($pagerAdapter);
|
||||
->orderBy('e.id', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,11 +21,12 @@
|
|||
{% if entries is empty %}
|
||||
<div class="messages warning"><p>{% trans %}No articles found.{% endtrans %}</p></div>
|
||||
{% 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 %}
|
||||
<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>
|
||||
{% if entry.content| readingTime > 0 %}
|
||||
<div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.content| readingTime }} min</span></div>
|
||||
{% if entry.readingTime > 0 %}
|
||||
<div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min</span></div>
|
||||
{% else %}
|
||||
<div class="estimatedTime"><span class="tool reading-time">{% trans %}estimated reading time :{% endtrans %} <small class="inferieur"><</small> 1 min</span></div>
|
||||
{% endif %}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
<pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate>
|
||||
<description>
|
||||
<![CDATA[
|
||||
{%- if entry.content|readingTime > 0 -%}
|
||||
{% trans %}estimated reading time :{% endtrans %} {{ entry.content|readingTime }} min
|
||||
{%- if entry.readingTime > 0 -%}
|
||||
{% trans %}estimated reading time :{% endtrans %} {{ entry.readingTime }} min
|
||||
{%- else -%}
|
||||
{% trans %}estimated reading time :{% endtrans %} < 1 min
|
||||
{%- endif %}
|
||||
|
|
|
@ -121,7 +121,7 @@ a:visited {
|
|||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
#main #content .entrie {
|
||||
#main #content .entry {
|
||||
margin-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px dashed #222;
|
||||
|
@ -129,19 +129,19 @@ a:visited {
|
|||
}
|
||||
|
||||
/* First entry */
|
||||
#main #content .results + .entrie {
|
||||
#main #content .results + .entry {
|
||||
clear: both;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#main .entrie .tools {
|
||||
#main .entry .tools {
|
||||
float: right;
|
||||
text-align: right;
|
||||
list-style-type: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#main .entrie .tools .tool span {
|
||||
#main .entry .tools .tool span {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
|
|
@ -322,7 +322,7 @@ footer a {
|
|||
letter-spacing:-5px;
|
||||
}
|
||||
|
||||
.listmode .entrie {
|
||||
.listmode .entry {
|
||||
width: 100%!important;
|
||||
margin-left: 0!important;
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ footer a {
|
|||
top: -1px;
|
||||
}
|
||||
|
||||
.entrie {
|
||||
.entry {
|
||||
background-color: #FFF;
|
||||
letter-spacing:normal;
|
||||
box-shadow: 0 3px 7px rgba(0,0,0,0.3);
|
||||
|
@ -366,7 +366,7 @@ footer a {
|
|||
/* transition: all 0.5s ease; */
|
||||
}
|
||||
|
||||
.entrie:before {
|
||||
.entry:before {
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
@ -384,7 +384,7 @@ footer a {
|
|||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.entrie:after {
|
||||
.entry:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 7px;
|
||||
|
@ -399,34 +399,34 @@ footer a {
|
|||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.entrie:hover {
|
||||
.entry:hover {
|
||||
box-shadow: 0 3px 10px rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
.entrie:hover:after {
|
||||
.entry:hover:after {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.entrie:hover:before {
|
||||
.entry:hover:before {
|
||||
bottom: 2.4em;
|
||||
}
|
||||
|
||||
.entrie:hover h2 a {
|
||||
.entry:hover h2 a {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.entrie h2 {
|
||||
.entry h2 {
|
||||
text-transform: none;
|
||||
margin-bottom: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.entrie h2:after {
|
||||
.entry h2:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
|
||||
.entrie h2 a {
|
||||
.entry h2 a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
|
@ -438,7 +438,7 @@ footer a {
|
|||
transition: all 0.5s ease;
|
||||
}
|
||||
/*
|
||||
.entrie h2 a:after {
|
||||
.entry h2 a:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -448,21 +448,21 @@ footer a {
|
|||
}
|
||||
*/
|
||||
|
||||
.entrie p {
|
||||
.entry p {
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.entrie h2 a:first-letter {
|
||||
.entry h2 a:first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.entrie:hover .tools {
|
||||
.entry:hover .tools {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.entrie .tools {
|
||||
.entry .tools {
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
left: 0;
|
||||
|
@ -477,22 +477,22 @@ footer a {
|
|||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.entrie .tools a {
|
||||
.entry .tools a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.entrie .tools a:hover {
|
||||
.entry .tools a:hover {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.entrie .tools li {
|
||||
.entry .tools li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.entrie:nth-child(3n+1) {
|
||||
.entry:nth-child(3n+1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
@ -941,13 +941,13 @@ pre code {
|
|||
========================================================================== */
|
||||
|
||||
@media screen and (max-width: 1050px) {
|
||||
.entrie {
|
||||
.entry {
|
||||
width: 49%;
|
||||
}
|
||||
.entrie:nth-child(3n+1) {
|
||||
.entry:nth-child(3n+1) {
|
||||
margin-left: 1.5%;
|
||||
}
|
||||
.entrie:nth-child(2n+1) {
|
||||
.entry:nth-child(2n+1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
@ -962,7 +962,7 @@ pre code {
|
|||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.entrie {
|
||||
.entry {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
@ -972,7 +972,7 @@ pre code {
|
|||
}
|
||||
|
||||
@media screen and (max-width: 500px) {
|
||||
.entrie {
|
||||
.entry {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
{% if entries is not empty %}
|
||||
<div class="results clearfix">
|
||||
<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">
|
||||
{% for p in range(1, entries.nbPages) %}
|
||||
<li class="{{ currentPage == p ? 'active':'waves-effect'}}">
|
||||
|
@ -38,8 +39,8 @@
|
|||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title"><a href="{{ path('view', { 'id': entry.id }) }}">{{ entry.title|raw }}</a></span>
|
||||
{% if entry.content| readingTime > 0 %}
|
||||
<div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.content| readingTime }} min</span></div>
|
||||
{% if entry.readingTime > 0 %}
|
||||
<div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} {{ entry.readingTime }} min</span></div>
|
||||
{% else %}
|
||||
<div class="estimatedTime grey-text"><span class="tool reading-time">{% trans %}estimated reading time: {% endtrans %} <small class="inferieur"><</small> 1 min</span></div>
|
||||
{% endif %}
|
||||
|
|
|
@ -25,7 +25,7 @@ body > footer,
|
|||
div.tools,
|
||||
header div,
|
||||
.messages,
|
||||
.entrie + .results {
|
||||
.entry + .results {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -240,4 +240,23 @@ class EntryControllerTest extends WallabagCoreTestCase
|
|||
|
||||
$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]'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ class WallabagExtension extends \Twig_Extension
|
|||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
new \Twig_SimpleFilter('readingTime', array($this, 'getReadingTime')),
|
||||
new \Twig_SimpleFilter('domainName', array($this, 'getDomainName')),
|
||||
);
|
||||
}
|
||||
|
@ -24,18 +23,6 @@ class WallabagExtension extends \Twig_Extension
|
|||
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()
|
||||
{
|
||||
return 'wallabag_extension';
|
||||
|
|
Loading…
Reference in a new issue