Merge pull request #2662 from wallabag/add-list-view

Add list view
This commit is contained in:
Nicolas Lœuillet 2016-11-28 16:47:41 +01:00 committed by GitHub
commit ad51d77146
13 changed files with 175 additions and 19 deletions

View file

@ -0,0 +1,49 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Added list_mode in user config.
*/
class Version20161128084725 extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
private function getTable($tableName)
{
return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$configTable = $schema->getTable($this->getTable('config'));
$this->skipIf($configTable->hasColumn('list_mode'), 'It seems that you already played this migration.');
$configTable->addColumn('list_mode', 'integer');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$configTable = $schema->getTable($this->getTable('config'));
$configTable->dropColumn('list_mode');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

View file

@ -297,18 +297,14 @@ h2::after {
text-decoration: none; text-decoration: none;
} }
#listmode a:hover {
opacity: 1;
}
#listmode.tablemode { #listmode.tablemode {
background-image: url("../img/baggy/table.png"); background-image: url("../../_global/img/table.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: bottom; background-position: bottom;
} }
#listmode.listmode { #listmode.listmode {
background-image: url("../img/baggy/list.png"); background-image: url("../../_global/img/list.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: bottom; background-position: bottom;
} }
@ -352,9 +348,9 @@ footer a {
letter-spacing: -5px; letter-spacing: -5px;
} }
.listmode .entry { .listmode.entry {
width: 100% !important; width: 100%;
margin-left: 0 !important; height: inherit;
} }
.card-entry-labels { .card-entry-labels {
@ -588,6 +584,7 @@ div.pagination ul {
text-align: left; text-align: left;
font-style: italic; font-style: italic;
color: #999; color: #999;
display: inline-flex;
} }
div.pagination ul > * { div.pagination ul > * {
@ -620,6 +617,10 @@ div.pagination ul .current {
background-color: #ccc; background-color: #ccc;
} }
.hide {
display: none;
}
/* ========================================================================== /* ==========================================================================
2.1 = "save a link" related styles 2.1 = "save a link" related styles
========================================================================== */ ========================================================================== */

View file

@ -194,7 +194,6 @@ main,
.results { .results {
height: 1em; height: 1em;
line-height: 30px;
} }
.results .nb-results, .results .nb-results,
@ -203,6 +202,14 @@ main,
margin-bottom: 0; margin-bottom: 0;
} }
.results .nb-results {
display: inline-flex;
}
.results a {
color: #444;
}
.pagination { .pagination {
float: right; float: right;
} }
@ -548,6 +555,14 @@ a.original {
margin-right: 5px !important; margin-right: 5px !important;
} }
.card-stacked:hover ul.tools-list {
display: block;
}
.card-stacked ul.tools-list {
display: none;
}
.card .card-action a { .card .card-action a {
color: #fff; color: #fff;
margin: 0; margin: 0;

View file

@ -363,4 +363,25 @@ class ConfigController extends Controller
return $this->redirect($this->generateUrl('fos_user_security_login')); return $this->redirect($this->generateUrl('fos_user_security_login'));
} }
/**
* Switch view mode for current user.
*
* @Route("/config/view-mode", name="switch_view_mode")
*
* @param Request $request
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeViewModeAction(Request $request)
{
$user = $this->getUser();
$user->getConfig()->setListMode(!$user->getConfig()->getListMode());
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirect($request->headers->get('referer'));
}
} }

View file

@ -97,6 +97,13 @@ class Config
*/ */
private $actionMarkAsRead; private $actionMarkAsRead;
/**
* @var int
*
* @ORM\Column(name="list_mode", type="integer", nullable=true)
*/
private $listMode;
/** /**
* @ORM\OneToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="config") * @ORM\OneToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="config")
*/ */
@ -339,6 +346,26 @@ class Config
return $this; return $this;
} }
/**
* @return int
*/
public function getListMode()
{
return $this->listMode;
}
/**
* @param int $listMode
*
* @return Config
*/
public function setListMode($listMode)
{
$this->listMode = $listMode;
return $this;
}
/** /**
* @param TaggingRule $rule * @param TaggingRule $rule
* *

View file

@ -13,9 +13,11 @@
{% block content %} {% block content %}
{% set listMode = app.user.config.listMode %}
<div class="results"> <div class="results">
<div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div> <div class="nb-results">{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}</div>
<div class="pagination"> <div class="pagination">
<a href="{{ path('switch_view_mode') }}"><i class="listMode-btn material-icons md-36">{% if listMode == 0 %}list{% else %}view_module{% endif %}</i></a>
<i class="btn-clickable download-btn material-icons md-36">file_download</i> <i class="btn-clickable download-btn material-icons md-36">file_download</i>
<i class="btn-clickable filter-btn material-icons md-36">filter_list</i> <i class="btn-clickable filter-btn material-icons md-36">filter_list</i>
{% if entries.getNbPages > 1 %} {% if entries.getNbPages > 1 %}
@ -25,7 +27,7 @@
</div> </div>
{% for entry in entries %} {% for entry in entries %}
<div id="entry-{{ entry.id|e }}" class="entry"> <div id="entry-{{ entry.id|e }}" class="{% if listMode == 0 %}entry{% else %}listmode entry{% endif %}">
<h2><a href="{{ path('view', { 'id': entry.id }) }}" title="{{ entry.title|raw }}">{{ entry.title|raw }}</a></h2> <h2><a href="{{ path('view', { 'id': entry.id }) }}" title="{{ entry.title|raw }}">{{ entry.title|raw }}</a></h2>
{% set readingTime = entry.readingTime / app.user.config.readingSpeed %} {% set readingTime = entry.readingTime / app.user.config.readingSpeed %}
@ -50,13 +52,13 @@
<li><a title="{{ 'entry.list.delete'|trans }}" class="tool delete icon-trash icon" href="{{ path('delete_entry', { 'id': entry.id }) }}"><span>{{ 'entry.list.delete'|trans }}</span></a></li> <li><a title="{{ 'entry.list.delete'|trans }}" class="tool delete icon-trash icon" href="{{ path('delete_entry', { 'id': entry.id }) }}"><span>{{ 'entry.list.delete'|trans }}</span></a></li>
<li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon-link icon"><span>{{ entry.domainName|removeWww }}</span></a></li> <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon-link icon"><span>{{ entry.domainName|removeWww }}</span></a></li>
</ul> </ul>
{% if entry.previewPicture is null %} {% if (entry.previewPicture is null or listMode == 1) %}
<ul class="card-entry-tags"> <ul class="card-entry-tags">
{% for tag in entry.tags %} {% for tag in entry.tags %}
<li><a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a></li> <li><a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<p>{{ entry.content|striptags|slice(0, 300) }}&hellip;</p> <p {% if listMode == 1 %}class="hide"{% endif %}>{{ entry.content|striptags|slice(0, 300) }}&hellip;</p>
{% else %} {% else %}
<ul class="card-entry-labels"> <ul class="card-entry-labels">
{% for tag in entry.tags | slice(0, 3) %} {% for tag in entry.tags | slice(0, 3) %}

View file

@ -0,0 +1,18 @@
<div class="card">
<div class="card-stacked">
<div class="card-content">
<span class="card-title dot-ellipsis dot-resize-update">
<a href="{{ path('view', { 'id': entry.id }) }}" title="{{ entry.title | raw | striptags }}">
{{ entry.title| striptags | truncate(120, true, '…') | raw }}
</a>
</span>
<ul class="tools-list right">
<li>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}redo{% endif %}</i></a>
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
<a title="{{ 'entry.list.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a>
</li>
</ul>
</div>
</div>
</div>

View file

@ -12,9 +12,11 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% set listMode = app.user.config.listMode %}
<div class="results clearfix"> <div class="results clearfix">
<div class="nb-results left"> <div class="nb-results left">
{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }} {{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}
<a href="{{ path('switch_view_mode') }}"><i class="material-icons">{% if listMode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
</div> </div>
{% if entries.getNbPages > 1 %} {% if entries.getNbPages > 1 %}
{{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }} {{ pagerfanta(entries, 'twitter_bootstrap_translated', {'proximity': 1}) }}
@ -24,8 +26,10 @@
<br /> <br />
<ul class="row data"> <ul class="row data">
{% for entry in entries %} {% for entry in entries %}
<li id="entry-{{ entry.id|e }}" class="col l3 m6 s12"> <li id="entry-{{ entry.id|e }}" class="col {% if listMode == 0 %}l3 m6{% endif %} s12">
{% if entry.previewPicture is null %} {% if listMode == 1 %}
{% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry} only %}
{% elseif entry.previewPicture is null %}
{% include "@WallabagCore/themes/material/Entry/_card_no_preview.html.twig" with {'entry': entry} only %} {% include "@WallabagCore/themes/material/Entry/_card_no_preview.html.twig" with {'entry': entry} only %}
{% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %} {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
{% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %} {% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %}

View file

@ -1,6 +1,6 @@
<?php <?php
namespace Tests\Wallabag\CoreBundle\Controller; namespace tests\Wallabag\CoreBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Wallabag\CoreBundle\Entity\Config; use Wallabag\CoreBundle\Entity\Config;
@ -836,4 +836,23 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertEmpty($annotationsReset, 'Annotations were reset'); $this->assertEmpty($annotationsReset, 'Annotations were reset');
} }
public function testSwitchViewMode()
{
$this->logInAs('admin');
$client = $this->getClient();
$client->request('GET', '/unread/list');
$this->assertNotContains('listmode', $client->getResponse()->getContent());
$client->request('GET', '/config/view-mode');
$crawler = $client->followRedirect();
$client->request('GET', '/unread/list');
$this->assertContains('listmode', $client->getResponse()->getContent());
$client->request('GET', '/config/view-mode');
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long