mirror of
https://github.com/wallabag/wallabag.git
synced 2024-11-23 09:31:04 +00:00
commit
ad51d77146
13 changed files with 175 additions and 19 deletions
49
app/DoctrineMigrations/Version20161128084725.php
Normal file
49
app/DoctrineMigrations/Version20161128084725.php
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
BIN
app/Resources/static/themes/_global/img/list.png
Executable file
BIN
app/Resources/static/themes/_global/img/list.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 201 B |
BIN
app/Resources/static/themes/_global/img/table.png
Executable file
BIN
app/Resources/static/themes/_global/img/table.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 229 B |
|
@ -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
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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) }}…</p>
|
<p {% if listMode == 1 %}class="hide"{% endif %}>{{ entry.content|striptags|slice(0, 300) }}…</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) %}
|
||||||
|
|
|
@ -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>
|
|
@ -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 %}
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue