]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #2314 from wallabag/assets
authorNicolas Lœuillet <nicolas@loeuillet.org>
Mon, 3 Oct 2016 07:09:45 +0000 (09:09 +0200)
committerGitHub <noreply@github.com>
Mon, 3 Oct 2016 07:09:45 +0000 (09:09 +0200)
Assets work

123 files changed:
app/DoctrineMigrations/Version20160812120952.php
app/Resources/static/themes/material/css/main.css
app/config/config.yml
app/config/routing.yml
app/config/security.yml
app/config/services.yml
docker/php/Dockerfile
docs/de/conf.py
docs/de/developer/docker.rst
docs/de/developer/rabbitmq.rst [new file with mode: 0644]
docs/de/developer/redis.rst [new file with mode: 0644]
docs/de/index.rst
docs/de/user/upgrade-2.0.x-2.0.y.rst [moved from docs/de/user/upgrade.rst with 77% similarity]
docs/de/user/upgrade-2.0.x-2.1.y.rst [new file with mode: 0644]
docs/en/conf.py
docs/en/developer/docker.rst
docs/en/developer/rabbitmq.rst
docs/en/developer/redis.rst
docs/en/index.rst
docs/en/user/import.rst
docs/en/user/upgrade-2.0.x-2.0.y.rst [moved from docs/en/user/upgrade.rst with 70% similarity]
docs/en/user/upgrade-2.0.x-2.1.y.rst [new file with mode: 0644]
docs/fr/conf.py
docs/fr/developer/docker.rst
docs/fr/developer/rabbitmq.rst [new file with mode: 0644]
docs/fr/developer/redis.rst [new file with mode: 0644]
docs/fr/index.rst
docs/fr/user/import.rst
docs/fr/user/upgrade-2.0.x-2.0.y.rst [moved from docs/fr/user/upgrade.rst with 74% similarity]
docs/fr/user/upgrade-2.0.x-2.1.y.rst [new file with mode: 0644]
src/Wallabag/ApiBundle/Controller/WallabagRestController.php
src/Wallabag/CoreBundle/Command/InstallCommand.php
src/Wallabag/CoreBundle/Controller/ConfigController.php
src/Wallabag/CoreBundle/Controller/DeveloperController.php
src/Wallabag/CoreBundle/Controller/EntryController.php
src/Wallabag/CoreBundle/Controller/ExceptionController.php [new file with mode: 0644]
src/Wallabag/CoreBundle/Controller/RssController.php
src/Wallabag/CoreBundle/Controller/StaticController.php
src/Wallabag/CoreBundle/Helper/EntriesExport.php
src/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverter.php
src/Wallabag/CoreBundle/Repository/EntryRepository.php
src/Wallabag/CoreBundle/Resources/config/services.yml
src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
src/Wallabag/CoreBundle/Resources/translations/validators.da.yml
src/Wallabag/CoreBundle/Resources/translations/validators.tr.yml
src/Wallabag/CoreBundle/Resources/views/base.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Exception/error.html.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/about.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/howto.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/quickstart.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/baggy/layout.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/client.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/baggy/Developer/client.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/client_parameters.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/baggy/Developer/client_parameters.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/howto_app.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/baggy/Developer/howto_app.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Developer/index.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/baggy/Developer/index.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/_title.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/_title.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/entries.xml.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/baggy/Entry/entries.xml.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Entry/share.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/share.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Mail/forgotPassword.txt.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/common/Static/_bookmarklet.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/_bookmarklet.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Static/about.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/material/Static/about.html.twig with 100% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig [moved from src/Wallabag/CoreBundle/Resources/views/themes/material/Static/howto.html.twig with 95% similarity]
src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client_parameters.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/howto_app.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/index.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig
src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.xml.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/Exception/error.html.twig [new file with mode: 0644]
src/Wallabag/CoreBundle/Resources/views/themes/material/Static/quickstart.html.twig [deleted file]
src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig
src/Wallabag/CoreBundle/Twig/WallabagExtension.php
src/Wallabag/ImportBundle/Command/RedisWorkerCommand.php
src/Wallabag/ImportBundle/Controller/ImportController.php
src/Wallabag/ImportBundle/Controller/InstapaperController.php [new file with mode: 0644]
src/Wallabag/ImportBundle/Import/AbstractImport.php
src/Wallabag/ImportBundle/Import/BrowserImport.php
src/Wallabag/ImportBundle/Import/InstapaperImport.php [new file with mode: 0644]
src/Wallabag/ImportBundle/Import/ReadabilityImport.php
src/Wallabag/ImportBundle/Import/WallabagImport.php
src/Wallabag/ImportBundle/Resources/config/rabbit.yml
src/Wallabag/ImportBundle/Resources/config/redis.yml
src/Wallabag/ImportBundle/Resources/config/services.yml
src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig [new file with mode: 0644]
src/Wallabag/UserBundle/Controller/ManageController.php [new file with mode: 0644]
src/Wallabag/UserBundle/Entity/User.php
src/Wallabag/UserBundle/EventListener/CreateConfigListener.php [moved from src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php with 53% similarity]
src/Wallabag/UserBundle/Form/NewUserType.php [moved from src/Wallabag/CoreBundle/Form/Type/NewUserType.php with 77% similarity]
src/Wallabag/UserBundle/Form/UserType.php [new file with mode: 0644]
src/Wallabag/UserBundle/Resources/config/services.yml
src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig [new file with mode: 0644]
src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig [new file with mode: 0644]
src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig [new file with mode: 0644]
src/Wallabag/UserBundle/Resources/views/Registration/check_email.html.twig [moved from src/Wallabag/UserBundle/Resources/views/Registration/checkEmail.html.twig with 100% similarity]
src/Wallabag/UserBundle/Resources/views/manage.html.twig [new file with mode: 0644]
tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php
tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php
tests/Wallabag/CoreBundle/WallabagCoreTestCase.php
tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php
tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php [new file with mode: 0644]
tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php [new file with mode: 0644]
tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv [new file with mode: 0644]
tests/Wallabag/UserBundle/Controller/ManageControllerTest.php [new file with mode: 0644]
tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php [moved from tests/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListenerTest.php with 83% similarity]
tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php

index 9adfdc8be35e87f66fcc49fac5c161e56ef1ae75..a8d3bcf25a9382852a9d90e69c330b0b2eb4df71 100644 (file)
@@ -29,7 +29,11 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
      */
     public function up(Schema $schema)
     {
-        $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
+        if ($this->connection->getDatabasePlatform()->getName() == 'sqlite') {
+            $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL');
+        } else {
+            $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
+        }
     }
 
     /**
index 67be1d22911828eaf59c611d3ce1a534f1d6b56a..00d7a8699e1f52320cbf87566c08846e4d459f37 100755 (executable)
@@ -348,7 +348,6 @@ main ul.row {
 .card .card-content .card-title {
   line-height: 32px;
   max-height: 64px;
-  display: block;
 }
 
 .card .card-content i.right,
@@ -409,12 +408,12 @@ main ul.row {
 }
 
 .card .card-action a {
-  color: #fff;
+  color: #fff !important;
   margin: 0;
 }
 
 .card .card-action a:hover {
-  color: #fff;
+  color: #fff !important;
 }
 
 .settings .div_tabs {
index a4584a1ba435cd66cb12f42f904e938f14735cc5..fbebfee7f1f2420f53e7568c51d237f9c931be01 100644 (file)
@@ -55,7 +55,7 @@ wallabag_user:
     registration_enabled: "%fosuser_registration%"
 
 wallabag_import:
-    allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain']
+    allow_mimetypes: ['application/octet-stream', 'application/json', 'text/plain', 'text/csv']
     resource_dir: "%kernel.root_dir%/../web/uploads/import"
 
 # Twig Configuration
@@ -64,6 +64,7 @@ twig:
     strict_variables: "%kernel.debug%"
     form_themes:
         - "LexikFormFilterBundle:Form:form_div_layout.html.twig"
+    exception_controller: wallabag_core.exception_controller:showAction
 
 # Doctrine Configuration
 doctrine:
@@ -236,6 +237,11 @@ old_sound_rabbit_mq:
             exchange_options:
                 name: 'wallabag.import.readability'
                 type: topic
+        import_instapaper:
+            connection: default
+            exchange_options:
+                name: 'wallabag.import.instapaper'
+                type: topic
         import_wallabag_v1:
             connection: default
             exchange_options:
@@ -273,6 +279,14 @@ old_sound_rabbit_mq:
             queue_options:
                 name: 'wallabag.import.readability'
             callback: wallabag_import.consumer.amqp.readability
+        import_instapaper:
+            connection: default
+            exchange_options:
+                name: 'wallabag.import.instapaper'
+                type: topic
+            queue_options:
+                name: 'wallabag.import.instapaper'
+            callback: wallabag_import.consumer.amqp.instapaper
         import_wallabag_v1:
             connection: default
             exchange_options:
index 40cc7165bb4e410f175a330fa591e2f79ea70e59..2be74d7f08fcc46d960e193f3098e2405bcf58e0 100644 (file)
@@ -7,6 +7,11 @@ wallabag_import:
     type: annotation
     prefix: /import
 
+wallabag_user:
+    resource: "@WallabagUserBundle/Controller/"
+    type: annotation
+    prefix: /users
+
 wallabag_api:
     resource: "@WallabagApiBundle/Resources/config/routing.yml"
     prefix: /
index 1f30e58b845abceb50011a28ed32b0f7ab57daca..efb00a5348135d7ad16f94ec3760f0a7771564d7 100644 (file)
@@ -63,4 +63,5 @@ security:
         - { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/settings, roles: ROLE_SUPER_ADMIN }
         - { path: ^/annotations, roles: ROLE_USER }
+        - { path: ^/users, roles: ROLE_SUPER_ADMIN }
         - { path: ^/, roles: ROLE_USER }
index 76bbce27c741b49aeae4898e87ca469305630d35..a57ef0f3d42e43f0d24c96dcb56183769d7b1b03 100644 (file)
@@ -21,6 +21,7 @@ services:
             - "@wallabag_core.tag_repository"
             - "@security.token_storage"
             - "%wallabag_core.cache_lifetime%"
+            - "@translator"
         tags:
             - { name: twig.extension }
 
index 29d27c3a80ce1a3fa933f824492d0e0f02c1e9d5..1fb1f29826e7c402cecb9274006767dea4dd4558 100644 (file)
@@ -4,9 +4,10 @@ FROM php:fpm
 ARG timezone='Europe/Paris'
 
 RUN apt-get update && apt-get install -y \
-        libmcrypt-dev libicu-dev libpq-dev libxml2-dev \
+        libmcrypt-dev libicu-dev libpq-dev libxml2-dev libpng12-dev libjpeg-dev \
+    && /usr/local/bin/docker-php-ext-configure gd --with-jpeg-dir=/usr/include \
     && docker-php-ext-install \
-        iconv mcrypt mbstring intl pdo pdo_mysql pdo_pgsql
+        iconv mcrypt mbstring intl pdo pdo_mysql pdo_pgsql gd
 
 RUN echo "date.timezone="$timezone > /usr/local/etc/php/conf.d/date_timezone.ini
 
index 8f2d130d08b202bf8956de229cec206ee9aa5029..cc9dcdf810698b3d6428ce929e2de2c541471c0f 100644 (file)
@@ -12,7 +12,7 @@ source_suffix = '.rst'
 master_doc = 'index'
 project = u'wallabag-fr'
 copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence'
-version = '2.0.0'
+version = '2.1.0'
 release = version
 exclude_patterns = ['_build']
 pygments_style = 'sphinx'
index c63194aadd9864f2f6b030113987d6012cff4af6..9948fe8c79796f14d57469ef2bbd883a4eb2fdb5 100644 (file)
@@ -44,7 +44,7 @@ wallabag laufen lassen
    Eigenschaften mit den kommentierten zu ersetzen (mit Werten
    mit ``env.`` Präfix)
 #. ``composer install`` die Projektabhängigkeiten
-#. ``php app/console wallabag:install``, um das Schema zu erstellen
+#. ``php bin/console wallabag:install``, um das Schema zu erstellen
 #. ``docker-compose up`` um die Container laufen zu lassen
 #. Schließlich öffne http://localhost:8080/, um dein frisch
    installiertes wallabag zu finden.
diff --git a/docs/de/developer/rabbitmq.rst b/docs/de/developer/rabbitmq.rst
new file mode 100644 (file)
index 0000000..bea02ff
--- /dev/null
@@ -0,0 +1,77 @@
+Installiere RabbitMQ für asynchrone Aufgaben
+============================================
+
+Um asynchrone Aufgaben zu starten (nützlich z.B. für große Imports), können wir RabbitMQ nutzen.
+
+Voraussetzungen
+---------------
+
+Du musst RabbitMQ auf deinem Server installiert haben.
+
+Installation
+~~~~~~~~~~~~
+
+.. code:: bash
+
+  wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc
+  apt-key add rabbitmq-signing-key-public.asc
+  apt-get update
+  apt-get install rabbitmq-server
+
+Konfiguration und Starten
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+  rabbitmq-plugins enable rabbitmq_management # (useful to have a web interface, available at http://localhost:15672/ (guest/guest)
+  rabbitmq-server -detached
+
+RabbitMQ stoppen
+~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+  rabbitmqctl stop
+
+
+Konfigure RabbitMQ in wallabag
+------------------------------
+
+Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
+
+.. code:: yaml
+
+    rabbitmq_host: localhost
+    rabbitmq_port: 5672
+    rabbitmq_user: guest
+    rabbitmq_password: guest
+
+
+Starte den RabbitMQ Consumer
+----------------------------
+
+Abhängig von welchem Service du importieren möchtest, solltest du einen Cron Job aktivieren (oder mehrere, wenn du viele unterstützen willst):
+
+.. code:: bash
+
+  # for Pocket import
+  bin/console rabbitmq:consumer import_pocket -w
+
+  # for Readability import
+  bin/console rabbitmq:consumer import_readability -w
+
+  # for Instapaper import
+  bin/console rabbitmq:consumer import_instapaper -w
+
+  # for wallabag v1 import
+  bin/console rabbitmq:consumer import_wallabag_v1 -w
+
+  # for wallabag v2 import
+  bin/console rabbitmq:consumer import_wallabag_v2 -w
+
+  # for Firefox import
+  bin/console rabbitmq:consumer import_firefox -w
+
+  # for Chrome import
+  bin/console rabbitmq:consumer import_chrome -w
+
diff --git a/docs/de/developer/redis.rst b/docs/de/developer/redis.rst
new file mode 100644 (file)
index 0000000..d613ce6
--- /dev/null
@@ -0,0 +1,71 @@
+Installiere Redis für asynchrone Aufgaben
+=========================================
+
+Um asynchrone Aufgaben zu starten (nützlich z.B. für große Imports), können wir Redis nutzen.
+
+Voraussetzungen
+---------------
+
+Du musst Redis auf deinem Server installiert haben.
+
+Installation
+~~~~~~~~~~~~
+
+.. code:: bash
+
+  apt-get install redis-server
+
+Starten
+~~~~~~
+
+Der Redis Service läuft eventuell schon direkt nach der Installation. Falls nicht kannst du ihn wie folgt starten:
+
+.. code:: bash
+
+  redis-server
+
+
+Konfigure Redis in wallabag
+---------------------------
+
+Bearbeite die Datei ``parameters.yml``, um die RabbitMQ Konfiguration einzurichten. Die Standardkonfiguration sollte ok sein:
+
+.. code:: yaml
+
+    redis_host: localhost
+    redis_port: 6379
+
+
+Starte den Redis Consumer
+-------------------------
+
+Abhängig von welchem Service du importieren möchtest, solltest du einen Cron Job aktivieren (oder mehrere, wenn du viele unterstützen willst):
+
+.. code:: bash
+
+  # for Pocket import
+  bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log
+
+  # for Readability import
+  bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log
+
+  # for Instapaper import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log
+
+  # for wallabag v1 import
+  bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log
+
+  # for wallabag v2 import
+  bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log
+
+  # for Firefox import
+  bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
+
+  # for Chrome import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+
+Wenn du den Import nur für ein paar Nachrichten und nicht für alle starten willst, kannst du die Nummer (im folgenden Beispiel 12) angeben. Der Redis Worker wird dann nach der 12. Nachricht stoppen:
+
+.. code:: bash
+
+  bin/console wallabag:import:redis-worker pocket -vv --maxIterations=12
index d8cd8f396bbfe3e6baca7f48d51f0341ade171d9..b3cd33b07a8b471d877bee4eaa3721a60b7416e3 100644 (file)
@@ -30,7 +30,8 @@ Die Dokumentation ist in anderen Sprachen verfügbar :
 
    user/faq
    user/installation
-   user/upgrade
+   user/upgrade-2.0.x-2.1.y
+   user/upgrade-2.0.x-2.0.y
    user/migration
    user/import
    user/create_account
@@ -55,3 +56,5 @@ Die Dokumentation ist in anderen Sprachen verfügbar :
    developer/documentation
    developer/translate
    developer/maintenance
+   developer/redis
+   developer/rabbitmq
similarity index 77%
rename from docs/de/user/upgrade.rst
rename to docs/de/user/upgrade-2.0.x-2.0.y.rst
index 953c84ff7cd1c5437551298cf219378f21d4355f..adf288bd501db0139ede85abd3efd417c187df06 100644 (file)
@@ -1,17 +1,18 @@
-Wallabag updaten
-================
+Wallabag updaten 2.0.x -> 2.1.x
+===============================
 
 Update auf einem dedizierten Webserver
 --------------------------------------
 
-Das neueste Release ist auf https://www.wallabag.org/pages/download-wallabag.html veröffentlicht. Um deine wallabag Installation auf die neueste Version upzudaten, führe die folgenden Kommandos in deinem wallabag Ordner aus (ersetze ``2.1.0`` mit der neuesten Releasenummer):
+Das neueste Release ist auf https://www.wallabag.org/pages/download-wallabag.html veröffentlicht. Um deine wallabag Installation auf die neueste Version upzudaten, führe die folgenden Kommandos in deinem wallabag Ordner aus (ersetze ``2.0.8`` mit der neuesten Releasenummer):
 
 ::
 
     git fetch origin
     git fetch --tags
-    git checkout 2.1.0
-    ./install.sh
+    git checkout 2.0.8
+    SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
+    php bin/console cache:clear --env=prod
 
 Update auf einem Shared Webhosting
 ----------------------------------
diff --git a/docs/de/user/upgrade-2.0.x-2.1.y.rst b/docs/de/user/upgrade-2.0.x-2.1.y.rst
new file mode 100644 (file)
index 0000000..85229d3
--- /dev/null
@@ -0,0 +1,64 @@
+Wallabag updaten
+================
+
+.. warning::
+Wenn du den Import von Pocket durch das Hinzufügen des Consumer Key in den internen Einstellungen konfiguriert hast, fertige bitte ein Backup deines Keys an, bevor du auf das neue Release migrierst: Du wirst den Key nach dem Update in der Konfiguration erneut eintragen müssen.
+
+Update auf einem dedizierten Webserver
+--------------------------------------
+
+Das neueste Release ist auf https://www.wallabag.org/pages/download-wallabag.html veröffentlicht. Um deine wallabag-Installation auf die neueste Version zu aktualisieren, führe die folgenden Kommandos in deinem wallabag-Ordner aus (ersetze ``2.1.0`` mit der neuesten Releasenummer):
+
+::
+
+    git fetch origin
+    git fetch --tags
+    git checkout 2.1.0
+    ASSETS=build ./install.sh
+    php bin/console doctrine:migrations:migrate --env=prod
+    php bin/console cache:clear --env=prod
+
+Update auf einem Shared Webhosting
+----------------------------------
+
+Sichere deine ``app/config/parameters.yml`` Datei.
+
+Lade das neueste Release von wallabag herunter:
+
+.. code-block:: bash
+
+    wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+
+(md5 hash: ``4f84c725d1d6e3345eae0a406115e5ff``)
+
+Entpacke das Archiv in deinen wallabag-Ordner und ersetze ``app/config/parameters.yml`` mit deiner Datei.
+
+Bitte beachte, dass wir in dieser Version neue Parameter hinzugefügt haben. Du musst die Datei ``app/config/parameters.yml`` bearbeiten und die folgenden Zeilen hinzufügen (ersetze die Werte mit deiner Konfiguration):
+
+.. code-block:: bash
+
+    # RabbitMQ processing
+    rabbitmq_host: localhost
+    rabbitmq_port: 5672
+    rabbitmq_user: guest
+    rabbitmq_password: guest
+
+    # Redis processing
+    redis_host: localhost
+    redis_port: 6379
+
+Wenn du SQLite nutzt, musst auch das ``data/`` Verzeichnis in die neue Installation kopieren.
+
+Leere den ``var/cache`` Ordner.
+
+Du musst einige SQL-Abfragen ausführen, um die Datenbank zu aktualisieren. Wir nehmen in diesem Fall an, dass das Tabellenpräfix ``wallabag_`` ist und eine MySQL-Datenbank genutzt wird:
+
+.. code-block:: sql
+
+    ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
+    ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
+    ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
+    DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
index 86e337040978a243bb746120fb8281a00ca3f214..717b35f1433fb2cfe290e82eb5b00132d6efbf6b 100644 (file)
@@ -12,7 +12,7 @@ source_suffix = '.rst'
 master_doc = 'index'
 project = u'wallabag'
 copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence'
-version = '2.0.0'
+version = '2.1.0'
 release = version
 exclude_patterns = ['_build']
 pygments_style = 'sphinx'
index 8816cbcfbdc2cdf395b29e2383bbeadb756f0a93..5e4f2ce6bda0326e2ff0c4ae306f199b3480c046 100644 (file)
@@ -40,7 +40,7 @@ Run wallabag
 #. Edit ``app/config/parameters.yml`` to replace ``database_*``
    properties with commented ones (with values prefixed by ``env.``)
 #. ``composer install`` the project dependencies
-#. ``php app/console wallabag:install`` to create the schema
+#. ``php bin/console wallabag:install`` to create the schema
 #. ``docker-compose up`` to run the containers
 #. Finally, browse to http://localhost:8080/ to find your freshly
    installed wallabag.
index 8cee45fb6eb5c90a84656b21361d1d9a1019d2b3..63b851063f85c49b27deae04118235bfbffc817e 100644 (file)
@@ -57,11 +57,20 @@ Depending on which service you want to import from you need to enable one (or ma
   # for Pocket import
   bin/console rabbitmq:consumer import_pocket -w
 
-  # for Readbility import
+  # for Readability import
   bin/console rabbitmq:consumer import_readability -w
 
+  # for Instapaper import
+  bin/console rabbitmq:consumer import_instapaper -w
+
   # for wallabag v1 import
   bin/console rabbitmq:consumer import_wallabag_v1 -w
 
   # for wallabag v2 import
   bin/console rabbitmq:consumer import_wallabag_v2 -w
+
+  # for Firefox import
+  bin/console rabbitmq:consumer import_firefox -w
+
+  # for Chrome import
+  bin/console rabbitmq:consumer import_chrome -w
index 5748e260de9e363ceeab11987251dac52f1499ff..820a52e9e62603509b9f3705a12cdbec9a1fb862 100644 (file)
@@ -1,5 +1,5 @@
 Install Redis for asynchronous tasks
-=======================================
+====================================
 
 In order to launch asynchronous tasks (useful for huge imports for example), we can use Redis.
 
@@ -37,7 +37,7 @@ Edit your ``parameters.yml`` file to edit Redis configuration. The default one s
 
 
 Launch Redis consumer
-------------------------
+---------------------
 
 Depending on which service you want to import from you need to enable one (or many if you want to support many) cron job:
 
@@ -46,15 +46,24 @@ Depending on which service you want to import from you need to enable one (or ma
   # for Pocket import
   bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log
 
-  # for Readbility import
+  # for Readability import
   bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log
 
+  # for Instapaper import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log
+
   # for wallabag v1 import
   bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log
 
   # for wallabag v2 import
   bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log
 
+  # for Firefox import
+  bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
+
+  # for Chrome import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+
 If you want to launch the import only for some messages and not all, you can specify this number (here 12) and the worker will stop right after the 12th message :
 
 .. code:: bash
index 46450b8f0fd5cf0455828679df875c07e57af8f6..beb3816e1a9fa02d5cbf5dda8fc523cf72ca32e6 100644 (file)
@@ -30,7 +30,8 @@ The documentation is available in other languages:
 
    user/faq
    user/installation
-   user/upgrade
+   user/upgrade-2.0.x-2.1.y
+   user/upgrade-2.0.x-2.0.y
    user/migration
    user/import
    user/create_account
@@ -56,3 +57,5 @@ The documentation is available in other languages:
    developer/documentation
    developer/translate
    developer/maintenance
+   developer/redis
+   developer/rabbitmq
index e6c37d722c48a746357ce408367c477462317337..758e38169e6bfddb66d4aeaddfc9302e31d30281 100644 (file)
@@ -23,12 +23,11 @@ Now, all is fine to migrate from Pocket.
 Import your data into wallabag 2.x
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Click on  ``Import`` link in the menu, on ``Import contents`` in Pocket section
+Click on ``Import`` link in the menu, on ``Import contents`` in Pocket section
 and then on ``Connect to Pocket and import data``.
 
 You need to authorize wallabag to interact with your Pocket account.
-Your data will be imported. Data import can be a demanding process for your server
-(we need to work on this import to improve it).
+Your data will be imported. Data import can be a demanding process for your server.
 
 From Readability
 ----------------
@@ -41,15 +40,26 @@ On the tools (`https://www.readability.com/tools/<https://www.readability.com/to
 Import your data into wallabag 2.x
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Click on  ``Import`` link in the menu, on ``Import contents`` in Readability section
+Click on ``Import`` link in the menu, on ``Import contents`` in Readability section
 and then select your json file and upload it.
 
-Your data will be imported. Data import can be a demanding process for your server (we need to work on this import to improve it).
+Your data will be imported. Data import can be a demanding process for your server.
 
 From Instapaper
 ---------------
 
-*Feature not yet implemented in wallabag v2.*
+Export your Instapaper data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the settings (`https://www.instapaper.com/user<https://www.instapaper.com/user>`_) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like ``instapaper-export.csv``).
+
+Import your data into wallabag 2.x
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Click on ``Import`` link in the menu, on ``Import contents`` in Instapaper section
+and then select your CSV file and upload it.
+
+Your data will be imported. Data import can be a demanding process for your server.
 
 From HTML or JSON file
 ----------------------
similarity index 70%
rename from docs/en/user/upgrade.rst
rename to docs/en/user/upgrade-2.0.x-2.0.y.rst
index 5c37be95088ad052f03719b8086bd32e03dead05..6a0818b3a5e234474c98b099ce19494f66854a33 100644 (file)
@@ -1,17 +1,18 @@
-Upgrade wallabag
-================
+Upgrade from 2.0.x to 2.0.y
+===========================
 
 Upgrade on a dedicated web server
 ---------------------------------
 
-The last release is published on https://www.wallabag.org/pages/download-wallabag.html. In order to upgrade your wallabag installation and get the last version, run the following commands in you wallabag folder (replace ``2.1.0`` by the last release number):
+The last release is published on https://www.wallabag.org/pages/download-wallabag.html. In order to upgrade your wallabag installation and get the last version, run the following commands in you wallabag folder (replace ``2.0.8`` by the last release number):
 
 ::
 
     git fetch origin
     git fetch --tags
-    git checkout 2.1.0
-    ./install.sh
+    git checkout 2.0.8
+    SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
+    php bin/console cache:clear --env=prod
 
 Upgrade on a shared hosting
 ---------------------------
@@ -24,7 +25,7 @@ Download the last release of wallabag:
 
     wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
 
-(md5 hash of the package: ``4f84c725d1d6e3345eae0a406115e5ff``)
+(md5 hash of the 2.0.8 package: ``4f84c725d1d6e3345eae0a406115e5ff``)
 
 Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours.
 
diff --git a/docs/en/user/upgrade-2.0.x-2.1.y.rst b/docs/en/user/upgrade-2.0.x-2.1.y.rst
new file mode 100644 (file)
index 0000000..5ae5eb4
--- /dev/null
@@ -0,0 +1,64 @@
+Upgrading from 2.0.x to 2.1.y
+=============================
+
+.. warning::
+Before this migration, if you configured the Pocket import by adding your consumer key in Internal settings, please do a backup of it: you'll have to add it into the Config page after the upgrade.
+
+Upgrade on a dedicated web server
+---------------------------------
+
+The last release is published on https://www.wallabag.org/pages/download-wallabag.html. In order to upgrade your wallabag installation and get the last version, run the following commands in you wallabag folder (replace ``2.1.0`` by the last release number):
+
+::
+
+    git fetch origin
+    git fetch --tags
+    git checkout 2.1.0
+    ASSETS=build ./install.sh
+    php bin/console doctrine:migrations:migrate --env=prod
+    php bin/console cache:clear --env=prod
+
+Upgrade on a shared hosting
+---------------------------
+
+Backup your ``app/config/parameters.yml`` file.
+
+Download the last release of wallabag:
+
+.. code-block:: bash
+
+    wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+
+(md5 hash of the package: ``4f84c725d1d6e3345eae0a406115e5ff``)
+
+Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours.
+
+Please note that we added new parameters in this version. You have to edit ``app/config/parameters.yml`` by adding these lines (replace with your configuration) :
+
+.. code-block:: bash
+
+    # RabbitMQ processing
+    rabbitmq_host: localhost
+    rabbitmq_port: 5672
+    rabbitmq_user: guest
+    rabbitmq_password: guest
+
+    # Redis processing
+    redis_host: localhost
+    redis_port: 6379
+
+If you use SQLite, you must also copy your ``data/`` folder inside the new installation.
+
+Empty ``var/cache`` folder.
+
+You must run some SQL queries to upgrade your database. We assume that the table prefix is ``wallabag_`` and the database server is a MySQL one:
+
+.. code-block:: sql
+
+    ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
+    ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
+    ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
+    DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
index f1fe39676a13cc2e88bda28cdc1c9a3f10ea3247..49a57e2d5dc97b22216363860139796f533f1fed 100644 (file)
@@ -12,7 +12,7 @@ source_suffix = '.rst'
 master_doc = 'index'
 project = u'wallabag-fr'
 copyright = u'2013-2016, Nicolas Lœuillet - MIT Licence'
-version = '2.0.0'
+version = '2.1.0'
 release = version
 exclude_patterns = ['_build']
 pygments_style = 'sphinx'
index 73cb56be833d7dd920212d2da444bfa1bdf3c58b..84724ed3eae9ab9fcc734d3bb3b8aedb08f62edf 100644 (file)
@@ -39,7 +39,7 @@ Exécuter wallabag
 #. Editer ``app/config/parameters.yml`` pour remplacer les propriétés ``database_*``
     par les lignes commentées (celles avec des valeurs préfixées par ``env.``)
 #. ``composer install`` pour installer les dépendances
-#. ``php app/console wallabag:install`` pour créer le schéma de la BDD
+#. ``php bin/console wallabag:install`` pour créer le schéma de la BDD
 #. ``docker-compose up`` pour démarrer les conteneurs
 #. Enfin, se rendre sur http://localhost:8080/ pour accéder à une installation
     tout propre de wallabag.
diff --git a/docs/fr/developer/rabbitmq.rst b/docs/fr/developer/rabbitmq.rst
new file mode 100644 (file)
index 0000000..20182e6
--- /dev/null
@@ -0,0 +1,76 @@
+Installer RabbitMQ pour des tâches asynchrones
+==============================================
+
+Pour lancer des tâches asynchrones (utile pour des imports importants par exemple), nous pouvons utiliser RabbitMQ.
+
+Pré-requis
+----------
+
+Vous devez installer RabbitMQ sur votre serveur.
+
+Installation
+~~~~~~~~~~~~
+
+.. code:: bash
+
+  wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc
+  apt-key add rabbitmq-signing-key-public.asc
+  apt-get update
+  apt-get install rabbitmq-server
+
+Configuration et démarrage
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+  rabbitmq-plugins enable rabbitmq_management # (useful to have a web interface, available at http://localhost:15672/ (guest/guest)
+  rabbitmq-server -detached
+
+Arrêter RabbitMQ
+~~~~~~~~~~~~~~~~
+
+.. code:: bash
+
+  rabbitmqctl stop
+
+
+Configurer RabbitMQ dans wallabag
+---------------------------------
+
+Modifiez votre fichier ``parameters.yml`` pour éditer la configuration RabbitMQ. Celle par défaut devrait convenir :
+
+.. code:: yaml
+
+    rabbitmq_host: localhost
+    rabbitmq_port: 5672
+    rabbitmq_user: guest
+    rabbitmq_password: guest
+
+
+Démarrer les clients RabbitMQ
+-----------------------------
+
+En fonction du service dont vous souhaitez importer vos données, vous devez activer un (ou plusieurs si vous souhaitez en supporter plusieurs) cron job :
+
+.. code:: bash
+
+  # for Pocket import
+  bin/console rabbitmq:consumer import_pocket -w
+
+  # for Readability import
+  bin/console rabbitmq:consumer import_readability -w
+
+  # for Instapaper import
+  bin/console rabbitmq:consumer import_instapaper -w
+
+  # for wallabag v1 import
+  bin/console rabbitmq:consumer import_wallabag_v1 -w
+
+  # for wallabag v2 import
+  bin/console rabbitmq:consumer import_wallabag_v2 -w
+
+  # for Firefox import
+  bin/console rabbitmq:consumer import_firefox -w
+
+  # for Chrome import
+  bin/console rabbitmq:consumer import_chrome -w
diff --git a/docs/fr/developer/redis.rst b/docs/fr/developer/redis.rst
new file mode 100644 (file)
index 0000000..097e375
--- /dev/null
@@ -0,0 +1,71 @@
+Installer Redis pour des tâches asynchrones
+===========================================
+
+Pour lancer des tâches asynchrones (utile pour des imports importants par exemple), nous pouvons utiliser Redis.
+
+Pré-requis
+----------
+
+Vous devez installer Redis sur votre serveur.
+
+Installation
+~~~~~~~~~~~~
+
+.. code:: bash
+
+  apt-get install redis-server
+
+Démarrage
+~~~~~~~~~
+
+Le serveur devrait déjà être démarré après l'installation. Si ce n'est pas le cas, vous pouvez le démarrer ainsi :
+
+.. code:: bash
+
+  redis-server
+
+
+Configurer Redis dans wallabag
+-------------------------------
+
+Modifiez votre fichier ``parameters.yml`` pour éditer la configuration Redis. Celle par défaut devrait convenir :
+
+.. code:: yaml
+
+    redis_host: localhost
+    redis_port: 6379
+
+
+Démarrer les clients Redis
+--------------------------
+
+En fonction du service dont vous souhaitez importer vos données, vous devez activer un (ou plusieurs si vous souhaitez en supporter plusieurs) cron job :
+
+.. code:: bash
+
+  # for Pocket import
+  bin/console wallabag:import:redis-worker pocket -vv >> /path/to/wallabag/var/logs/redis-pocket.log
+
+  # for Readability import
+  bin/console wallabag:import:redis-worker readability -vv >> /path/to/wallabag/var/logs/redis-readability.log
+
+  # for Instapaper import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-instapaper.log
+
+  # for wallabag v1 import
+  bin/console wallabag:import:redis-worker wallabag_v1 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v1.log
+
+  # for wallabag v2 import
+  bin/console wallabag:import:redis-worker wallabag_v2 -vv >> /path/to/wallabag/var/logs/redis-wallabag_v2.log
+
+  # for Firefox import
+  bin/console wallabag:import:redis-worker firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
+
+  # for Chrome import
+  bin/console wallabag:import:redis-worker instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+
+Si vous souhaitez démarrer l'import pour quelques messages uniquement, vous pouvez spécifier cette valeur en paramètre (ici 12) et le client va s'arrêter après le 12ème message :
+
+.. code:: bash
+
+  bin/console wallabag:import:redis-worker pocket -vv --maxIterations=12
index dfa55afe676049c629c26545d94d29e7c4032a05..359b103c0aa14231a2fb5c75cb1e8116b82a5564 100644 (file)
@@ -31,7 +31,8 @@ La documentation est disponible dans d'autres langues :
 
    user/faq
    user/installation
-   user/upgrade
+   user/upgrade-2.0.x-2.1.y
+   user/upgrade-2.0.x-2.0.y
    user/migration
    user/import
    user/create_account
@@ -56,3 +57,5 @@ La documentation est disponible dans d'autres langues :
    developer/documentation
    developer/translate
    developer/maintenance
+   developer/redis
+   developer/rabbitmq
index 99ac602b6313c9f11127b294ff529b39ac507472..6f114dd6a9e3222ac2e5ad7377f7e242be3f2e7b 100644 (file)
@@ -28,7 +28,7 @@ la section Pocket puis sur ``Se connecter à Pocket et importer les données``.
 
 Vous devez autoriser wallabag à se connecter à votre compte Pocket.
 Vos données vont être importées. L'import de données est une action qui peut être couteuse
-pour votre serveur (nous devons encore travailler pour améliorer cet import).
+pour votre serveur.
 
 Depuis Readability
 ------------------
@@ -44,12 +44,23 @@ Importez vos données dans wallabag 2.x
 Cliquez sur le lien ``Importer`` dans le menu, sur  ``Importer les contenus`` dans
 la section Readability et ensuite sélectionnez votre fichier json pour l'uploader.
 
-Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur (nous devons encore travailler pour améliorer cet import).
+Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur.
 
 Depuis Instapaper
 -----------------
 
-*Fonctionnalité pas encore implémentée dans wallabag v2.*
+Exportez vos données de Instapaper
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sur la page des paramètres (`https://www.instapaper.com/user<https://www.instapaper.com/user>`_), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera (``instapaper-export.csv``).
+
+Importez vos données dans wallabag 2.x
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cliquez sur le lien ``Importer`` dans le menu, sur  ``Importer les contenus`` dans
+la section Instapaper et ensuite sélectionnez votre fichier CSV pour l'uploader.
+
+Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur.
 
 
 Depuis un fichier HTML ou JSON
similarity index 74%
rename from docs/fr/user/upgrade.rst
rename to docs/fr/user/upgrade-2.0.x-2.0.y.rst
index e3798979c4ac4bb7bb613d03d6728ee9481aac49..d8dfac6ebff807079a1b7b3175b899d6d0d1d9be 100644 (file)
@@ -1,17 +1,18 @@
-Mettre à jour wallabag
-======================
+Mettre à jour de la 2.0.x à la 2.0.y
+====================================
 
 Mise à jour sur un serveur dédié
 --------------------------------
 
-La dernière version de wallabag est publiée à cette adresse : https://www.wallabag.org/pages/download-wallabag.html. Pour mettre à jour votre installation de wallabag, exécutez les commandes suivantes dans votre répertoire d'installation (remplacez ``2.1.0`` par le numéro de la dernière version) :
+La dernière version de wallabag est publiée à cette adresse : https://www.wallabag.org/pages/download-wallabag.html. Pour mettre à jour votre installation de wallabag, exécutez les commandes suivantes dans votre répertoire d'installation (remplacez ``2.0.8`` par le numéro de la dernière version) :
 
 ::
 
     git fetch origin
     git fetch --tags
-    git checkout 2.1.0
-    ./install.sh
+    git checkout 2.0.8
+    SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
+    php bin/console cache:clear --env=prod
 
 Mise à jour sur un hébergement mutualisé
 ----------------------------------------
@@ -24,7 +25,7 @@ Téléchargez la dernière version de wallabag :
 
     wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
 
-(hash md5 de l'archive : ``4f84c725d1d6e3345eae0a406115e5ff``)
+(hash md5 de l'archive 2.0.8 : ``4f84c725d1d6e3345eae0a406115e5ff``)
 
 Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre.
 
diff --git a/docs/fr/user/upgrade-2.0.x-2.1.y.rst b/docs/fr/user/upgrade-2.0.x-2.1.y.rst
new file mode 100644 (file)
index 0000000..a4afe76
--- /dev/null
@@ -0,0 +1,65 @@
+Mettre à jour de la 2.0.x à la 2.1.y
+====================================
+
+.. warning::
+Avant cette migration, si vous aviez configuré l'import depuis Pocket en ajoutant votre consumer key dans les paramètres internes, pensez à effectuer une sauvegarde de celle-ci : vous devrez l'ajouter dans la configuration de wallabag après la mise à jour.
+
+Mise à jour sur un serveur dédié
+--------------------------------
+
+La dernière version de wallabag est publiée à cette adresse : https://www.wallabag.org/pages/download-wallabag.html. Pour mettre à jour votre installation de wallabag, exécutez les commandes suivantes dans votre répertoire d'installation (remplacez ``2.1.0`` par le numéro de la dernière version) :
+
+::
+
+    git fetch origin
+    git fetch --tags
+    git checkout 2.1.0
+    ASSETS=build ./install.sh
+    php bin/console doctrine:migrations:migrate --env=prod
+    php bin/console cache:clear --env=prod
+
+Mise à jour sur un hébergement mutualisé
+----------------------------------------
+
+Effectuez une sauvegarde du fichier ``app/config/parameters.yml``.
+
+Téléchargez la dernière version de wallabag :
+
+.. code-block:: bash
+
+    wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+
+(hash md5 de l'archive : ``4f84c725d1d6e3345eae0a406115e5ff``)
+
+Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre.
+
+Nous avons ajouté de nouveaux paramètres dans cette nouvelle version. Vous devez donc éditer le fichier ``app/config/parameters.yml`` en ajoutant ces lignes (et en remplaçant par votre configuration) :
+
+.. code-block:: bash
+
+    # RabbitMQ processing
+    rabbitmq_host: localhost
+    rabbitmq_port: 5672
+    rabbitmq_user: guest
+    rabbitmq_password: guest
+
+    # Redis processing
+    redis_host: localhost
+    redis_port: 6379
+
+Si vous utilisez SQLite, vous devez également conserver le contenu du répertoire ``data/``.
+
+Videz le répertoire ``var/cache``.
+
+Vous allez devoir également exécuter des requêtes SQL pour mettre à jour votre base de données. Nous partons du principe que le préfixe de vos tables est ``wallabag_`` et que le serveur SQL est un serveur MySQL :
+
+.. code-block:: sql
+
+    ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
+    ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
+    INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
+    ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
+    DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
+
index dd17ef976d38a6a3f8f49ae3b639a5ba5e65a94a..791bf80b2310b89e1416289811a07ca879294ccf 100644 (file)
@@ -22,6 +22,38 @@ class WallabagRestController extends FOSRestController
         }
     }
 
+    /**
+     * Check if an entry exist by url.
+     *
+     * @ApiDoc(
+     *       parameters={
+     *          {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"}
+     *       }
+     * )
+     *
+     * @return JsonResponse
+     */
+    public function getEntriesExistsAction(Request $request)
+    {
+        $this->validateAuthentication();
+
+        $url = $request->query->get('url', '');
+
+        if (empty($url)) {
+            throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$user->getId());
+        }
+
+        $res = $this->getDoctrine()
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findByUrlAndUserId($url, $this->getUser()->getId());
+
+        $exists = false === $res ? false : true;
+
+        $json = $this->get('serializer')->serialize(['exists' => $exists], 'json');
+
+        return (new JsonResponse())->setJson($json);
+    }
+
     /**
      * Retrieve all entries. It could be filtered by many options.
      *
@@ -50,8 +82,8 @@ class WallabagRestController extends FOSRestController
         $order = $request->query->get('order', 'desc');
         $page = (int) $request->query->get('page', 1);
         $perPage = (int) $request->query->get('perPage', 30);
-        $since = $request->query->get('since', 0);
         $tags = $request->query->get('tags', '');
+        $since = $request->query->get('since', 0);
 
         $pager = $this->getDoctrine()
             ->getRepository('WallabagCoreBundle:Entry')
@@ -63,7 +95,20 @@ class WallabagRestController extends FOSRestController
         $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
         $paginatedCollection = $pagerfantaFactory->createRepresentation(
             $pager,
-            new Route('api_get_entries', [], UrlGeneratorInterface::ABSOLUTE_URL)
+            new Route(
+                'api_get_entries',
+                [
+                    'archive' => $isArchived,
+                    'starred' => $isStarred,
+                    'sort' => $sort,
+                    'order' => $order,
+                    'page' => $page,
+                    'perPage' => $perPage,
+                    'tags' => $tags,
+                    'since' => $since,
+                ],
+                UrlGeneratorInterface::ABSOLUTE_URL
+            )
         );
 
         $json = $this->get('serializer')->serialize($paginatedCollection, 'json');
index 3873d2d366762b88241874bb27415696b0b1cca3..cc7c2c94cf268be86cd4de51d895404a7d433ec2 100644 (file)
@@ -2,6 +2,8 @@
 
 namespace Wallabag\CoreBundle\Command;
 
+use FOS\UserBundle\Event\UserEvent;
+use FOS\UserBundle\FOSUserEvents;
 use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
 use Symfony\Component\Console\Helper\Table;
 use Symfony\Component\Console\Input\ArrayInput;
@@ -236,14 +238,9 @@ class InstallCommand extends ContainerAwareCommand
 
         $em->persist($user);
 
-        $config = new Config($user);
-        $config->setTheme($this->getContainer()->getParameter('wallabag_core.theme'));
-        $config->setItemsPerPage($this->getContainer()->getParameter('wallabag_core.items_on_page'));
-        $config->setRssLimit($this->getContainer()->getParameter('wallabag_core.rss_limit'));
-        $config->setReadingSpeed($this->getContainer()->getParameter('wallabag_core.reading_speed'));
-        $config->setLanguage($this->getContainer()->getParameter('wallabag_core.language'));
-
-        $em->persist($config);
+        // dispatch a created event so the associated config will be created
+        $event = new UserEvent($user);
+        $this->getContainer()->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
 
         $this->defaultOutput->writeln('');
 
index 4f75511bf62cf5c7ee23b5ceb5eaeeb16a89248f..91cdcae506fe75f2176f84fbe3c31911c29d3a66 100644 (file)
@@ -11,7 +11,6 @@ use Wallabag\CoreBundle\Entity\Config;
 use Wallabag\CoreBundle\Entity\TaggingRule;
 use Wallabag\CoreBundle\Form\Type\ConfigType;
 use Wallabag\CoreBundle\Form\Type\ChangePasswordType;
-use Wallabag\CoreBundle\Form\Type\NewUserType;
 use Wallabag\CoreBundle\Form\Type\RssType;
 use Wallabag\CoreBundle\Form\Type\TaggingRuleType;
 use Wallabag\CoreBundle\Form\Type\UserInformationType;
@@ -106,7 +105,21 @@ class ConfigController extends Controller
 
         // handle tagging rule
         $taggingRule = new TaggingRule();
-        $newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $this->generateUrl('config').'#set5']);
+        $action = $this->generateUrl('config').'#set5';
+
+        if ($request->query->has('tagging-rule')) {
+            $taggingRule = $this->getDoctrine()
+                ->getRepository('WallabagCoreBundle:TaggingRule')
+                ->find($request->query->get('tagging-rule'));
+
+            if ($this->getUser()->getId() !== $taggingRule->getConfig()->getUser()->getId()) {
+                return $this->redirect($action);
+            }
+
+            $action = $this->generateUrl('config').'?tagging-rule='.$taggingRule->getId().'#set5';
+        }
+
+        $newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $action]);
         $newTaggingRule->handleRequest($request);
 
         if ($newTaggingRule->isValid()) {
@@ -122,45 +135,12 @@ class ConfigController extends Controller
             return $this->redirect($this->generateUrl('config').'#set5');
         }
 
-        // handle adding new user
-        $newUser = $userManager->createUser();
-        // enable created user by default
-        $newUser->setEnabled(true);
-        $newUserForm = $this->createForm(NewUserType::class, $newUser, [
-            'validation_groups' => ['Profile'],
-            'action' => $this->generateUrl('config').'#set6',
-        ]);
-        $newUserForm->handleRequest($request);
-
-        if ($newUserForm->isValid() && $this->get('security.authorization_checker')->isGranted('ROLE_SUPER_ADMIN')) {
-            $userManager->updateUser($newUser, true);
-
-            $config = new Config($newUser);
-            $config->setTheme($this->getParameter('wallabag_core.theme'));
-            $config->setItemsPerPage($this->getParameter('wallabag_core.items_on_page'));
-            $config->setRssLimit($this->getParameter('wallabag_core.rss_limit'));
-            $config->setLanguage($this->getParameter('wallabag_core.language'));
-            $config->setReadingSpeed($this->getParameter('wallabag_core.reading_speed'));
-
-            $em->persist($config);
-
-            $em->flush();
-
-            $this->get('session')->getFlashBag()->add(
-                'notice',
-                $this->get('translator')->trans('flashes.config.notice.user_added', ['%username%' => $newUser->getUsername()])
-            );
-
-            return $this->redirect($this->generateUrl('config').'#set6');
-        }
-
         return $this->render('WallabagCoreBundle:Config:index.html.twig', [
             'form' => [
                 'config' => $configForm->createView(),
                 'rss' => $rssForm->createView(),
                 'pwd' => $pwdForm->createView(),
                 'user' => $userForm->createView(),
-                'new_user' => $newUserForm->createView(),
                 'new_tagging_rule' => $newTaggingRule->createView(),
             ],
             'rss' => [
@@ -210,9 +190,7 @@ class ConfigController extends Controller
      */
     public function deleteTaggingRuleAction(TaggingRule $rule)
     {
-        if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) {
-            throw $this->createAccessDeniedException('You can not access this tagging rule.');
-        }
+        $this->validateRuleAction($rule);
 
         $em = $this->getDoctrine()->getManager();
         $em->remove($rule);
@@ -226,6 +204,34 @@ class ConfigController extends Controller
         return $this->redirect($this->generateUrl('config').'#set5');
     }
 
+    /**
+     * Edit a tagging rule.
+     *
+     * @param TaggingRule $rule
+     *
+     * @Route("/tagging-rule/edit/{id}", requirements={"id" = "\d+"}, name="edit_tagging_rule")
+     *
+     * @return RedirectResponse
+     */
+    public function editTaggingRuleAction(TaggingRule $rule)
+    {
+        $this->validateRuleAction($rule);
+
+        return $this->redirect($this->generateUrl('config').'?tagging-rule='.$rule->getId().'#set5');
+    }
+
+    /**
+     * Validate that a rule can be edited/deleted by the current user.
+     *
+     * @param TaggingRule $rule
+     */
+    private function validateRuleAction(TaggingRule $rule)
+    {
+        if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) {
+            throw $this->createAccessDeniedException('You can not access this tagging rule.');
+        }
+    }
+
     /**
      * Retrieve config for the current user.
      * If no config were found, create a new one.
@@ -238,6 +244,7 @@ class ConfigController extends Controller
             ->getRepository('WallabagCoreBundle:Config')
             ->findOneByUser($this->getUser());
 
+        // should NEVER HAPPEN ...
         if (!$config) {
             $config = new Config($this->getUser());
         }
index 63386db0c31147b7d3c639cf2c3a74a161e7ad94..f3492b74e77831ec1ad280596d0d74b99fcf489f 100644 (file)
@@ -21,7 +21,7 @@ class DeveloperController extends Controller
     {
         $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findAll();
 
-        return $this->render('WallabagCoreBundle:Developer:index.html.twig', [
+        return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [
             'clients' => $clients,
         ]);
     }
@@ -52,14 +52,14 @@ class DeveloperController extends Controller
                 $this->get('translator')->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()])
             );
 
-            return $this->render('WallabagCoreBundle:Developer:client_parameters.html.twig', [
+            return $this->render('@WallabagCore/themes/common/Developer/client_parameters.html.twig', [
                 'client_id' => $client->getPublicId(),
                 'client_secret' => $client->getSecret(),
                 'client_name' => $client->getName(),
             ]);
         }
 
-        return $this->render('WallabagCoreBundle:Developer:client.html.twig', [
+        return $this->render('@WallabagCore/themes/common/Developer/client.html.twig', [
             'form' => $clientForm->createView(),
         ]);
     }
@@ -96,6 +96,6 @@ class DeveloperController extends Controller
      */
     public function howtoFirstAppAction()
     {
-        return $this->render('WallabagCoreBundle:Developer:howto_app.html.twig');
+        return $this->render('@WallabagCore/themes/common/Developer/howto_app.html.twig');
     }
 }
index 40111af0b5e37a8209d28745d4e9281bee0225f7..3b28e635025253a8a7baa1c4eb6ff6c12600aba4 100644 (file)
@@ -531,7 +531,7 @@ class EntryController extends Controller
         }
 
         return $this->render(
-            '@WallabagCore/themes/share.html.twig',
+            '@WallabagCore/themes/common/Entry/share.html.twig',
             ['entry' => $entry]
         );
     }
diff --git a/src/Wallabag/CoreBundle/Controller/ExceptionController.php b/src/Wallabag/CoreBundle/Controller/ExceptionController.php
new file mode 100644 (file)
index 0000000..abfa9c2
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+namespace Wallabag\CoreBundle\Controller;
+
+use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * This controller allow us to customize the error template.
+ * The only modified line from the parent template is for "WallabagCoreBundle".
+ */
+class ExceptionController extends BaseExceptionController
+{
+    protected function findTemplate(Request $request, $format, $code, $showException)
+    {
+        $name = $showException ? 'exception' : 'error';
+        if ($showException && 'html' == $format) {
+            $name = 'exception_full';
+        }
+
+        // For error pages, try to find a template for the specific HTTP status code and format
+        if (!$showException) {
+            $template = sprintf('WallabagCoreBundle:Exception:%s.%s.twig', $name, $format);
+            if ($this->templateExists($template)) {
+                return $template;
+            }
+        }
+
+        // try to find a template for the given format
+        $template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format);
+        if ($this->templateExists($template)) {
+            return $template;
+        }
+
+        // default to a generic HTML exception
+        $request->setRequestFormat('html');
+
+        return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
+    }
+}
index 2118885c16f7607e7cbcd4fd8b452da4c9306df6..38e3b5a0ed7f2f7262f9aa3b98a887694d8b9df6 100644 (file)
@@ -87,7 +87,7 @@ class RssController extends Controller
         $perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit');
         $entries->setMaxPerPage($perPage);
 
-        return $this->render('WallabagCoreBundle:Entry:entries.xml.twig', [
+        return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [
             'type' => $type,
             'entries' => $entries,
         ]);
index 2a57f06fb055bc416ad037ed7a8580b91e4eea3c..82714217b1455ef9d9303405b6b72a619277ef5c 100644 (file)
@@ -15,7 +15,7 @@ class StaticController extends Controller
         $addonsUrl = $this->container->getParameter('addons_url');
 
         return $this->render(
-            'WallabagCoreBundle:Static:howto.html.twig',
+            '@WallabagCore/themes/common/Static/howto.html.twig',
             ['addonsUrl' => $addonsUrl]
         );
     }
@@ -26,7 +26,7 @@ class StaticController extends Controller
     public function aboutAction()
     {
         return $this->render(
-            'WallabagCoreBundle:Static:about.html.twig',
+            '@WallabagCore/themes/common/Static/about.html.twig',
             [
                 'version' => $this->getParameter('wallabag_core.version'),
                 'paypal_url' => $this->getParameter('wallabag_core.paypal_url'),
@@ -40,7 +40,7 @@ class StaticController extends Controller
     public function quickstartAction()
     {
         return $this->render(
-            'WallabagCoreBundle:Static:quickstart.html.twig',
+            '@WallabagCore/themes/common/Static/quickstart.html.twig',
             []
         );
     }
index 1dfa12c8bf99480e967f40a58be5d4e9fadc4a83..0c627dcdb6344fa687364d138b2d36bf217ddc89 100644 (file)
@@ -25,7 +25,7 @@ class EntriesExport
     private $footerTemplate = '<div style="text-align:center;">
         <p>Produced by wallabag with %EXPORT_METHOD%</p>
         <p>Please open <a href="https://github.com/wallabag/wallabag/issues">an issue</a> if you have trouble with the display of this E-Book on your device.</p>
-        </div';
+        </div>';
 
     /**
      * @param Config $craueConfig CraueConfig instance to get wallabag instance url from database
index 6ea2a4f3af29edbb1872291e61d4ac7fa684959f..40b5673ddf62310d61b9484a148b71bf1bb55281 100644 (file)
@@ -49,7 +49,7 @@ class UsernameRssTokenConverter implements ParamConverterInterface
         $em = $this->registry->getManagerForClass($configuration->getClass());
 
         // Check, if class name is what we need
-        if ('Wallabag\UserBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) {
+        if (null !== $em && 'Wallabag\UserBundle\Entity\User' !== $em->getClassMetadata($configuration->getClass())->getName()) {
             return false;
         }
 
@@ -69,9 +69,8 @@ class UsernameRssTokenConverter implements ParamConverterInterface
         $username = $request->attributes->get('username');
         $rssToken = $request->attributes->get('token');
 
-        // Check, if route attributes exists
-        if (null === $username || null === $rssToken) {
-            throw new \InvalidArgumentException('Route attribute is missing');
+        if (!$request->attributes->has('username') || !$request->attributes->has('token')) {
+            return false;
         }
 
         // Get actual entity manager for class
index 302e5a5387c6a64c72f79594d598988f288c6539..75127b7d9e69d5ec1cf5d5f815e439c2d3ba559c 100644 (file)
@@ -128,7 +128,7 @@ class EntryRepository extends EntityRepository
             $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred);
         }
 
-        if ($since >= 0) {
+        if ($since > 0) {
             $qb->andWhere('e.updatedAt > :since')->setParameter('since', new \DateTime(date('Y-m-d H:i:s', $since)));
         }
 
@@ -281,7 +281,7 @@ class EntryRepository extends EntityRepository
     public function findByUrlAndUserId($url, $userId)
     {
         $res = $this->createQueryBuilder('e')
-            ->where('e.url = :url')->setParameter('url', $url)
+            ->where('e.url = :url')->setParameter('url', urldecode($url))
             ->andWhere('e.user = :user_id')->setParameter('user_id', $userId)
             ->getQuery()
             ->getResult();
index 23e6d3ca91d2ea4f578a8ad0aab7aa16ce0f2e8f..d11398469757c4a60957a2a37c98adeca5b0dfd6 100644 (file)
@@ -88,17 +88,6 @@ services:
         arguments:
             - WallabagCoreBundle:Tag
 
-    wallabag_core.registration_confirmed:
-        class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener
-        arguments:
-            - "@doctrine.orm.entity_manager"
-            - "%wallabag_core.theme%"
-            - "%wallabag_core.items_on_page%"
-            - "%wallabag_core.rss_limit%"
-            - "%wallabag_core.language%"
-        tags:
-            - { name: kernel.event_subscriber }
-
     wallabag_core.helper.entries_export:
         class: Wallabag\CoreBundle\Helper\EntriesExport
         arguments:
@@ -133,3 +122,9 @@ services:
                 host: '%redis_host%'
                 port: '%redis_port%'
                 schema: tcp
+
+    wallabag_core.exception_controller:
+        class: Wallabag\CoreBundle\Controller\ExceptionController
+        arguments:
+            - '@twig'
+            - '%kernel.debug%'
index 9eeb210baffed20d20db0ce81efe4f7badad14c3..40644ff5f0062da2fce0d50b28cfe718ea4a8974 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Søg'
         # save_link: 'Save a link'
         back_to_unread: 'Tilbage til de ulæste artikler'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Tilføj ny artikel'
         search: 'Søg'
@@ -45,6 +46,7 @@ footer:
         # social: 'Social'
         # powered_by: 'powered by'
         about: 'Om'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Opsætning'
@@ -94,6 +96,7 @@ config:
         # if_label: 'if'
         # then_tag_as_label: 'then tag as'
         # delete_rule_label: 'delete'
+        # edit_rule_label: 'edit'
         # rule_label: 'Rule'
         # tags_label: 'Tags'
         # faq:
@@ -127,12 +130,6 @@ config:
         #         or: 'One rule OR another'
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
-    form_new_user:
-        username_label: 'Brugernavn'
-        password_label: 'Adgangskode'
-        repeat_new_password_label: 'Gentag adgangskode'
-        plain_password_label: '????'
-        email_label: 'Emailadresse'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     # page_title: 'Quickstart'
+    # more: 'More…'
     # intro:
     #     title: 'Welcome to wallabag!'
     #     paragraph_1: "We'll accompany you to visit wallabag and show you some features which can interest you."
     #     paragraph_2: 'Follow us!'
     # configure:
     #     title: 'Configure the application'
+    #     description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
     #     language: 'Change language and design'
     #     rss: 'Enable RSS feeds'
     #     tagging_rules: 'Write rules to automatically tag your articles'
@@ -285,6 +284,7 @@ quickstart:
     #     import: 'Configure import'
     # first_steps:
     #     title: 'First steps'
+    #     description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
     #     new_article: 'Save your first article'
     #     unread_articles: 'And classify it!'
     # migrate:
@@ -294,11 +294,15 @@ quickstart:
     #     wallabag_v1: 'Migrate from wallabag v1'
     #     wallabag_v2: 'Migrate from wallabag v2'
     #     readability: 'Migrate from Readability'
+    #     instapaper: 'Migrate from Instapaper'
     # developer:
     #     title: 'Developers'
+    #     description: 'We also thought to the developers: Docker, API, translations, etc.'
     #     create_application: 'Create your third application'
+    #     use_docker: 'Use Docker to install wallabag'
     # docs:
     #     title: 'Full documentation'
+    #     description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
     #     annotate: 'Annotate your article'
     #     export: 'Convert your articles into ePUB or PDF'
     #     search_filters: 'See how you can look for an article by using search engine and filters'
@@ -351,12 +355,16 @@ import:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
     # firefox:
     #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+    #    description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
     #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
     #chrome:
     #    page_title: 'Import > Chrome'
     #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
     #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    # instapaper:
+    #     page_title: 'Import > Instapaper'
+    #     description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+    #     how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     # page_title: 'Developer'
@@ -383,12 +391,14 @@ developer:
     #     page_title: 'Developer > New client'
     #     page_description: 'You are about to create a new client. Please fill the field below for the redirect URI of your application.'
     #     form:
+    #         name_label: 'Name of the client'
     #         redirect_uris_label: 'Redirect URIs'
     #         save_label: 'Create a new client'
     #     action_back: 'Back'
     # client_parameter:
     #     page_title: 'Developer > Client parameters'
     #     page_description: 'Here are your client parameters.'
+    #     field_name: 'Client name'
     #     field_id: 'Client ID'
     #     field_secret: 'Client secret'
     #     back: 'Back'
@@ -406,6 +416,33 @@ developer:
     #         paragraph_8: 'If you want to see all the API endpoints, you can have a look <a href="%link%">to our API documentation</a>.'
     #     back: 'Back'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Brugernavn'
+        # name_label: 'Name'
+        password_label: 'Adgangskode'
+        repeat_new_password_label: 'Gentag adgangskode'
+        plain_password_label: '????'
+        email_label: 'Emailadresse'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index a9ec25198c6c947dfad8cc56b352d6df5066cd30..6f79074407daa77b0d66038b71d02823197f3c91 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Suche'
         save_link: 'Link speichern'
         back_to_unread: 'Zurück zu ungelesenen Artikeln'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Neuen Artikel hinzufügen'
         search: 'Suche'
@@ -45,6 +46,7 @@ footer:
         social: 'Soziales'
         powered_by: 'angetrieben von'
         about: 'Über'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Einstellungen'
@@ -94,6 +96,7 @@ config:
         if_label: 'Wenn'
         then_tag_as_label: 'dann tagge als'
         delete_rule_label: 'löschen'
+        # edit_rule_label: 'edit'
         rule_label: 'Regel'
         tags_label: 'Tags'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: 'Eine Regel ODER die andere'
                 and: 'Eine Regel UND eine andere'
                 matches: 'Tests, ob eine <i>Variable</i> auf eine <i>Suche</i> zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).<br />Beispiel: <code>title matches "Fußball"</code>'
-    form_new_user:
-        username_label: 'Benutzername'
-        password_label: 'Kennwort'
-        repeat_new_password_label: 'Neues Kennwort wiederholen'
-        plain_password_label: '????'
-        email_label: 'E-Mail-Adresse'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Schnelleinstieg'
+    # more: 'More…'
     intro:
         title: 'Willkommen zu wallabag!'
         paragraph_1: "Wir werden dich bei der Benutzung von wallabag begleiten und dir einige Funktionen zeigen, die dich interessieren könnten."
         paragraph_2: 'Folge uns!'
     configure:
         title: 'Anwendung konfigurieren'
+        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: 'Sprache und Design ändern'
         rss: 'RSS-Feeds aktivieren'
         tagging_rules: 'Schreibe Regeln, um deine Beiträge automatisch zu taggen (verschlagworten)'
@@ -285,6 +284,7 @@ quickstart:
         import: 'Import-Einstellungen ändern'
     first_steps:
         title: 'Erste Schritte'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link"
         new_article: 'Speichere deinen ersten Artikel'
         unread_articles: 'Und klassifiziere ihn!'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'von wallabag v1 migrieren'
         wallabag_v2: 'von wallabag v2 migrieren'
         readability: 'von Readability migrieren'
+        instapaper: 'von Instapaper migrieren'
     developer:
         title: 'Entwickler'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Erstelle eine Anwendung und nutze die wallabag API'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Komplette Dokumentation'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Anmerkungen zu Artikeln hinzufügen'
         export: 'Artikel nach ePUB oder PDF konvertieren'
         search_filters: 'Schau nach, wie du nach einem Artikel über die Such- und Filterfunktion suchen kannst'
@@ -345,18 +349,22 @@ import:
         description: 'Dieser Import wird all deine Artikel aus wallabag v2 importieren. Gehe auf "Alle Artikel" und dann, in der Exportieren-Seitenleiste auf "JSON". Dabei erhältst du eine "All articles.json"-Datei.'
     readability:
         page_title: 'Aus Readability importieren'
-    #     description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
-    #     how_to: 'Please select your Readability export and click on the below button to upload and import it.'
+        # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
+        # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
     worker:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    firefox:
+        page_title: 'Aus Firefox importieren'
+        # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+        # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    chrome:
+        page_title: 'Aus Chrome importieren'
+        # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
+        # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'Aus Instapaper importieren'
+        # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     page_title: 'Entwickler'
@@ -383,12 +391,14 @@ developer:
         page_title: 'Entwickler > Neuer Client'
         page_description: 'Du bist dabei, einen neuen Client zu erstellen. Fülle das nachfolgende Feld für die Weiterleitungs-URIs deiner Anwendung aus.'
         form:
+            # name_label: 'Name of the client'
             redirect_uris_label: 'Weiterleitungs-URIs'
             save_label: 'Neuen Client erstellen'
         action_back: 'Zurück'
     client_parameter:
         page_title: 'Entwickler > Client-Parameter'
         page_description: 'Dies sind deine Client-Parameter.'
+        # field_name: 'Client name'
         field_id: 'Client-ID'
         field_secret: 'Client-Secret'
         back: 'Zurück'
@@ -406,6 +416,33 @@ developer:
             paragraph_8: 'Wenn du alle API-Endpunkte sehen willst, werfe einen Blick auf die <a href="%link%">API-Dokumentation</a>.'
         back: 'Zurück'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Benutzername'
+        # name_label: 'Name'
+        password_label: 'Kennwort'
+        repeat_new_password_label: 'Neues Kennwort wiederholen'
+        plain_password_label: '????'
+        email_label: 'E-Mail-Adresse'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index c0d8656d90e0e218e3d2231d196f2daa64b4f8d3..91abe16238735b535d3e9eae4e7a4cc6ca2640c0 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Search'
         save_link: 'Save a link'
         back_to_unread: 'Back to unread articles'
+        users_management: 'Users management'
     top:
         add_new_entry: 'Add a new entry'
         search: 'Search'
@@ -45,6 +46,7 @@ footer:
         social: 'Social'
         powered_by: 'powered by'
         about: 'About'
+    stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Config'
@@ -94,6 +96,7 @@ config:
         if_label: 'if'
         then_tag_as_label: 'then tag as'
         delete_rule_label: 'delete'
+        edit_rule_label: 'edit'
         rule_label: 'Rule'
         tags_label: 'Tags'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: 'One rule OR another'
                 and: 'One rule AND another'
                 matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
-    form_new_user:
-        username_label: 'Username'
-        password_label: 'Password'
-        repeat_new_password_label: 'Repeat new password'
-        plain_password_label: '????'
-        email_label: 'Email'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Quickstart'
+    more: 'More…'
     intro:
         title: 'Welcome to wallabag!'
         paragraph_1: "We'll accompany you on your visit to wallabag and show you some features that might interest you."
         paragraph_2: 'Follow us!'
     configure:
         title: 'Configure the application'
+        description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: 'Change language and design'
         rss: 'Enable RSS feeds'
         tagging_rules: 'Write rules to automatically tag your articles'
@@ -285,6 +284,7 @@ quickstart:
         import: 'Configure import'
     first_steps:
         title: 'First steps'
+        description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'Save your first article'
         unread_articles: 'And classify it!'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'Migrate from wallabag v1'
         wallabag_v2: 'Migrate from wallabag v2'
         readability: 'Migrate from Readability'
+        instapaper: 'Migrate from Instapaper'
     developer:
         title: 'Developers'
+        description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Create your third application'
+        use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Full documentation'
+        description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Annotate your article'
         export: 'Convert your articles into ePUB or PDF'
         search_filters: 'See how you can look for an article by using the search engine and filters'
@@ -351,12 +355,16 @@ import:
         enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
     firefox:
         page_title: 'Import > Firefox'
-        description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+        description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
         how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
     chrome:
         page_title: 'Import > Chrome'
         description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
         how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'Import > Instapaper'
+        description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     page_title: 'Developer'
@@ -408,6 +416,33 @@ developer:
             paragraph_8: 'If you want to see all the API endpoints, you can have a look <a href="%link%">to our API documentation</a>.'
         back: 'Back'
 
+user:
+    page_title: Users management
+    new_user: Create a new user
+    edit_user: Edit an existing user
+    description: "Here you can manage all users (create, edit and delete)"
+    list:
+        actions: Actions
+        edit_action: Edit
+        yes: Yes
+        no: No
+        create_new_one: Create a new user
+    form:
+        username_label: 'Username'
+        name_label: 'Name'
+        password_label: 'Password'
+        repeat_new_password_label: 'Repeat new password'
+        plain_password_label: '????'
+        email_label: 'Email'
+        enabled_label: 'Enabled'
+        locked_label: 'Locked'
+        last_login_label: 'Last login'
+        twofactor_label: Two factor authentication
+        save: Save
+        delete: Delete
+        delete_confirm: Are you sure?
+        back_to_list: Back to list
+
 flashes:
     config:
         notice:
@@ -418,7 +453,6 @@ flashes:
             rss_updated: 'RSS information updated'
             tagging_rules_updated: 'Tagging rules updated'
             tagging_rules_deleted: 'Tagging rule deleted'
-            user_added: 'User "%username%" added'
             rss_token_updated: 'RSS token updated'
     entry:
         notice:
@@ -449,3 +483,8 @@ flashes:
         notice:
             client_created: 'New client %name% created.'
             client_deleted: 'Client %name% deleted'
+    user:
+        notice:
+            added: 'User "%username%" added'
+            updated: 'User "%username%" updated'
+            deleted: 'User "%username%" deleted'
index 1d6993db0fff92bca34471a53f202e76943d277e..25d2f3a25c6d1aeb8dc0efcda59d65dc072bc9f9 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Buscar'
         save_link: 'Archivar un enlace'
         back_to_unread: 'Volver a los artículos sin leer'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Añadir un nuevo artículo'
         search: 'Buscar'
@@ -45,6 +46,7 @@ footer:
         social: 'Social'
         powered_by: 'funciona por'
         about: 'Acerca de'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Configuración'
@@ -94,6 +96,7 @@ config:
         if_label: 'si'
         then_tag_as_label: 'Etiquete como'
         delete_rule_label: 'Borre'
+        # edit_rule_label: 'edit'
         rule_label: 'Regla'
         tags_label: 'Etiquetas'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: 'Una regla U otra'
                 and: 'Una regla Y la otra'
                 matches: 'Pruebe si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>título coincide "football"</code>'
-    form_new_user:
-        username_label: 'Nombre de usuario'
-        password_label: 'Contraseña'
-        repeat_new_password_label: 'Confirmar la nueva contraseña'
-        plain_password_label: '????'
-        email_label: 'Email'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Comienzo rápido'
+    # more: 'More…'
     intro:
         title: 'Bienvenido a wallabag !'
         paragraph_1: "Le acompañaremos a su visita de wallabag y le mostraremos algunas características que le pueden interesar."
         paragraph_2: '¡Síganos!'
     configure:
         title: 'Configure la aplicación'
+        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: 'Cambie el idioma y el diseño de la aplicación'
         rss: 'Activar los feeds RSS'
         tagging_rules: 'Escribir reglas para etiquetear automaticamente sus artículos'
@@ -285,6 +284,7 @@ quickstart:
         import: 'Configure importación'
     first_steps:
         title: 'Primeros pasos'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'Guarde su primer artículo'
         unread_articles: '¡Y clasifíquelo!'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'Migrar desde wallabag v1'
         wallabag_v2: 'Migrar desde wallabag v2'
         readability: 'Migrar desde Readability'
+        instapaper: 'Migrar desde Instapaper'
     developer:
         title: 'Promotores'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Cree su tercera aplicación'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Documentación completa'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Anote su artículo'
         export: 'Convierta sus artículos a ePub o a PDF'
         search_filters: 'Aprenda a utilizar el buscador y los filtros para encontrar el artículo que le interese'
@@ -345,18 +349,22 @@ import:
         description: 'Va a importar sus artículos de otra instancia de wallabag v2. Vaya a Todos los artículos, entonces, en la barra lateral, oprima en "JSON". Usted tendrá un fichero "All articles.json"'
     readability:
         page_title: 'Importar > Readability'
-    #     description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
-    #     how_to: 'Please select your Readability export and click on the below button to upload and import it.'
+        # description: 'This importer will import all your Readability articles. On the tools (https://www.readability.com/tools/) page, click on "Export your data" in the "Data Export" section. You will received an email to download a json (which does not end with .json in fact).'
+        # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
     worker:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    firefox:
+       page_title: 'Importar > Firefox'
+       # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    chrome:
+       page_title: 'Importar > Chrome'
+       # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'Importar > Instapaper'
+        # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     page_title: 'Promotor'
@@ -383,12 +391,14 @@ developer:
         page_title: 'Promotor > Nuevo cliente'
         page_description: 'Va a crear un nuevo cliente. Por favor, llene el campo abajo para URI redirigido de su aplicación.'
         form:
+            # name_label: 'Name of the client'
             redirect_uris_label: 'los URI redirigidos'
             save_label: 'Crear un nuevo cliente'
         action_back: 'Atrás'
     client_parameter:
         page_title: 'Promotor > Parámetros del cliente'
         page_description: 'Aquí hay sus parámetros del cliente.'
+        # field_name: 'Client name'
         field_id: 'Identificación del cliente'
         field_secret: 'Cliente secreto'
         back: 'Atrás'
@@ -406,6 +416,33 @@ developer:
             paragraph_8: 'Si quiere ver todos los fines de API, se puede ver <a href="%link%">a nuestra documentación API</a>.'
         back: 'Atrás'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Nombre de usuario'
+        # name_label: 'Name'
+        password_label: 'Contraseña'
+        repeat_new_password_label: 'Confirmar la nueva contraseña'
+        plain_password_label: '????'
+        email_label: 'Email'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index 68272f99593c24ca76f4bf048ecdd8376d8bc3d3..b02ffea02fe1431397eeee328b1a93fbcf336ab2 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'جستجو'
         save_link: 'ذخیرهٔ یک پیوند'
         back_to_unread: 'بازگشت به خوانده‌نشده‌ها'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'افزودن مقالهٔ تازه'
         search: 'جستجو'
@@ -45,6 +46,7 @@ footer:
         social: 'شبکه‌های اجتماعی'
         powered_by: 'توانمند با'
         about: 'درباره'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'پیکربندی'
@@ -94,6 +96,7 @@ config:
         if_label: 'اگر'
         then_tag_as_label: 'این برچسب را بزن'
         delete_rule_label: 'پاک کن'
+        # edit_rule_label: 'edit'
         rule_label: 'قانون'
         tags_label: 'برچسب‌ها'
         faq:
@@ -127,12 +130,6 @@ config:
         #         or: 'One rule OR another'
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
-    form_new_user:
-        username_label: 'نام کاربری'
-        password_label: 'رمز'
-        repeat_new_password_label: 'رمز تازه را دوباره بنویسید'
-        plain_password_label: '????'
-        email_label: 'نشانی ایمیل'
 
 entry:
     page_titles:
@@ -266,6 +263,7 @@ howto:
 
 quickstart:
     page_title: 'Quickstart'
+    # more: 'More…'
     intro:
         title: 'به wallabag خوش آمدید!!'
         paragraph_1: "به شما کمک خواهیم کرد تا wallabag را بشناسید و با برخی از ویژگی‌های جالبش آشنا شوید"
@@ -285,6 +283,7 @@ quickstart:
         import: 'درون‌ریزی را تنظیم کنید'
     first_steps:
         title: 'گام نخست'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'نخستین مقالهٔ خود را ذخیره کنید'
         unread_articles: 'و آن را طبقه‌بندی کنید!'
     migrate:
@@ -294,11 +293,15 @@ quickstart:
         wallabag_v1: 'مهاجرت از نسخهٔ یکم wallabag'
         wallabag_v2: 'مهاجرت از نسخهٔ دوم wallabag'
         readability: 'مهاجرت از نسخهٔ دوم Readability'
+        instapaper: 'مهاجرت از نسخهٔ دوم Instapaper'
     developer:
         title: 'برنامه‌نویسان'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'برنامهٔ wallabag خود را بسازید'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'راهنمای کامل'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'روی مقاله‌هایتان یادداشت بگذارید'
         export: 'مقاله‌هایتان را به قالب ePUB یا PDF دربیاورید'
         search_filters: 'به کمک موتور جستجو و فیلترها به دنبال مقاله‌هایتان بگردید'
@@ -349,14 +352,18 @@ import:
         # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
     worker:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    firefox:
+       page_title: 'درون‌ریزی > Firefox'
+       # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    chrome:
+       page_title: 'درون‌ریزی > Chrome'
+       # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'درون‌ریزی > Instapaper'
+        # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     # page_title: 'Developer'
@@ -383,12 +390,14 @@ developer:
     #     page_title: 'Developer > New client'
     #     page_description: 'You are about to create a new client. Please fill the field below for the redirect URI of your application.'
     #     form:
+    #         name_label: 'Name of the client'
     #         redirect_uris_label: 'Redirect URIs'
     #         save_label: 'Create a new client'
     #     action_back: 'بازگشت'
     # client_parameter:
     #     page_title: 'Developer > Client parameters'
     #     page_description: 'Here are your client parameters.'
+    #     field_name: 'Client name'
     #     field_id: 'Client ID'
     #     field_secret: 'Client secret'
     #     back: 'بازگشت'
@@ -406,6 +415,33 @@ developer:
     #         paragraph_8: 'If you want to see all the API endpoints, you can have a look <a href="%link%">to our API documentation</a>.'
     #     back: 'بازگشت'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'نام کاربری'
+        # name_label: 'Name'
+        password_label: 'رمز'
+        repeat_new_password_label: 'رمز تازه را دوباره بنویسید'
+        plain_password_label: '????'
+        email_label: 'نشانی ایمیل'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index b28068b6bf2c221cf797538594a85310120095dd..598205b028129e26c2fc94551c5c49fa556dc088 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Recherche'
         save_link: 'Sauvegarder un nouvel article'
         back_to_unread: 'Retour aux articles non lus'
+        users_management: 'Gestion des utilisateurs'
     top:
         add_new_entry: 'Sauvegarder un nouvel article'
         search: 'Rechercher'
@@ -45,9 +46,10 @@ footer:
         social: 'Social'
         powered_by: 'propulsé par'
         about: 'À propos'
-    page_title: 'Configuration'
+    stats: Depuis le %user_creation% vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
 
 config:
+    page_title: 'Configuration'
     tab_menu:
         settings: 'Paramètres'
         rss: 'RSS'
@@ -94,6 +96,7 @@ config:
         if_label: 'si'
         then_tag_as_label: 'alors attribuer les tags'
         delete_rule_label: 'supprimer'
+        edit_rule_label: 'éditer'
         rule_label: 'Règle'
         tags_label: 'Tags'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: "Une règle OU l'autre"
                 and: "Une règle ET l'autre"
                 matches: 'Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches "football"</code>'
-    form_new_user:
-        username_label: "Nom d'utilisateur"
-        password_label: 'Mot de passe'
-        repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
-        plain_password_label: 'Mot de passe en clair'
-        email_label: 'Adresse e-mail'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Pour bien débuter'
+    more: 'Et plus encore…'
     intro:
         title: 'Bienvenue sur wallabag !'
         paragraph_1: "Nous allons vous accompagner pour vous faire faire le tour de la maison et vous présenter quelques fonctionnalités qui pourraient vous intéresser pour vous approprier cet outil."
         paragraph_2: 'Suivez-nous !'
     configure:
         title: "Configurez l'application"
+        description: 'Pour voir une application qui vous correspond, allez voir du côté de la configuration de wallabag.'
         language: "Changez la langue et le design de l'application"
         rss: 'Activez les flux RSS'
         tagging_rules: 'Écrivez des règles pour classer automatiquement vos articles'
@@ -285,6 +284,7 @@ quickstart:
         import: "Configurer l'import"
     first_steps:
         title: 'Premiers pas'
+        description: "Maintenant que wallabag est bien configuré, il est temps d'archiver le web. Vous pouvez cliquer sur le signe + dans le coin en haut à droite."
         new_article: 'Ajoutez votre premier article'
         unread_articles: 'Et rangez-le !'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'Migrer depuis wallabag v1'
         wallabag_v2: 'Migrer depuis wallabag v2'
         readability: 'Migrer depuis Readability'
+        instapaper: 'Migrer depuis Instapaper'
     developer:
         title: 'Pour les développeurs'
+        description: 'Nous avons aussi pensé aux développeurs : Docker, API, traductions, etc.'
         create_application: 'Créer votre application tierce'
+        use_docker: 'Utiliser Docker pour installer wallabag'
     docs:
         title: 'Documentation complète'
+        description: "Il y a tellement de fonctionnalités dans wallabag. N'hésitez pas à lire le manuel pour les connaitre et apprendre comment les utiliser."
         annotate: 'Annoter votre article'
         export: 'Convertissez vos articles en ePub ou en PDF'
         search_filters: "Apprenez à utiliser le moteur de recherche et les filtres pour retrouver l'article qui vous intéresse"
@@ -351,12 +355,16 @@ import:
         enabled: "Les imports sont asynchrones. Une fois l'import commencé un worker externe traitera les messages un par un. Le service activé est :"
     firefox:
         page_title: 'Import > Firefox'
-        description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox. <p>Pour Firefox, ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>"
+        description: "Cet outil va vous permettre d'importer tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json. </p>"
         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
     chrome:
         page_title: 'Import > Chrome'
         description: "Cet outil va vous permettre d'importer tous vos marques-pages de Google Chrome/Chromium. Pour Google Chrome, la situation du fichier dépend de votre système d'exploitation : <ul><li>Sur GNU/Linux, allez dans le répertoire <code>~/.config/google-chrome/Default/</code></li><li>Sous Windows, il devrait se trouver à <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Sur OS X, il devrait se trouver dans le fichier <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Une fois que vous y êtes, copiez le fichier Bookmarks à un endroit où vous le retrouverez.<em><br>Notez que si vous utilisez Chromium à la place de Chrome, vous devez corriger les chemins en conséquence.</em></p>"
         how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour l'importer. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
+    instapaper:
+        page_title: 'Import > Instapaper'
+        description: 'Sur la page des paramètres (`https://www.instapaper.com/user<https://www.instapaper.com/user>`_), cliquez sur "Download .CSV file" dans la section "Export". Un fichier CSV se téléchargera ("instapaper-export.csv").'
+        how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour l'importer."
 
 developer:
     page_title: 'Développeur'
@@ -408,6 +416,33 @@ developer:
             paragraph_8: "Si vous voulez toutes les méthodes de l'API, jetez un oeil <a href=\"%link%\">à la documentation de l'API</a>."
         back: 'Retour'
 
+user:
+    page_title: Gestion des utilisateurs
+    new_user: Créer un nouvel utilisateur
+    edit_user: Éditer un utilisateur existant
+    description: Ici vous pouvez gérer vos utilisateurs (création, mise à jour et suppression)
+    list:
+        actions: Actions
+        edit_action: Éditer
+        yes: Oui
+        no: Non
+        create_new_one: Créer un nouvel utilisateur
+    form:
+        username_label: "Nom d'utilisateur"
+        name_label: 'Nom'
+        password_label: 'Mot de passe'
+        repeat_new_password_label: 'Confirmez votre nouveau mot de passe'
+        plain_password_label: 'Mot de passe en clair'
+        email_label: 'Adresse e-mail'
+        enabled_label: 'Activé'
+        locked_label: 'Bloqué'
+        last_login_label: 'Dernière connexion'
+        twofactor_label: Double authentification
+        save: Sauvegarder
+        delete: Supprimer
+        delete_confirm: Êtes-vous sûr?
+        back_to_list: Revenir à la liste
+
 flashes:
     config:
         notice:
index bd98c8c0a75fa41a6738d3912af5f1a1caf08463..c58c929f78f31cfddac4aeac1cd65722866ff1ca 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Cerca'
         save_link: 'Salva collegamento'
         back_to_unread: 'Torna ai contenuti non letti'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Aggiungi un nuovo contenuto'
         search: 'Cerca'
@@ -45,6 +46,7 @@ footer:
         social: 'Social'
         powered_by: 'powered by'
         about: 'About'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Configurazione'
@@ -94,6 +96,7 @@ config:
         if_label: 'se'
         then_tag_as_label: 'allora tagga come'
         delete_rule_label: 'elimina'
+        # edit_rule_label: 'edit'
         rule_label: 'Regola'
         tags_label: 'Tag'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: "Una regola O un'altra"
                 and: "Una regola E un'altra"
                 matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
-    form_new_user:
-        username_label: 'Username'
-        password_label: 'Password'
-        repeat_new_password_label: 'Ripeti password'
-        plain_password_label: '????'
-        email_label: 'E-mail'
 
 entry:
     page_titles:
@@ -160,6 +157,7 @@ entry:
         status_label: 'Stato'
         archived_label: 'Archiviati'
         starred_label: 'Preferiti'
+        # unread_label: 'Unread'
         preview_picture_label: "Ha un'immagine di anteprima"
         preview_picture_help: 'Immagine di anteprima'
         language_label: 'Lingua'
@@ -265,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Introduzione'
+    # more: 'More…'
     intro:
         title: 'Benvenuto su wallabag!'
         paragraph_1: "Un tour in cui ti guideremo per scoprire e che ti mostrerà delle funzionalità che potrebbero interessarti."
         paragraph_2: 'Seguici!'
     configure:
         title: "Configura l'applicazione"
+        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: 'Cambia lingua e design'
         rss: 'Abilita i feed RSS'
         tagging_rules: 'Scrivi delle regole per taggare automaticamente i contenuti'
@@ -284,6 +284,7 @@ quickstart:
         import: "Configura l'importazione"
     first_steps:
         title: 'Pimi passi'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'Salva il tuo primo contenuto'
         unread_articles: 'E classificalo!'
     migrate:
@@ -293,11 +294,15 @@ quickstart:
         wallabag_v1: 'Trasferisci da wallabag v1'
         wallabag_v2: 'Trasferisci da wallabag v2'
         readability: 'Trasferisci da Readability'
+        instapaper: 'Trasferisci da Instapaper'
     developer:
         title: 'Sviluppatori'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Crea la tua applicazione'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Documentazione completa'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Annota il tuo contenuto'
         export: 'Converti i tuoi contenuti in EPUB o PDF'
         search_filters: 'Impara come puoi recuperare un contenuto tramite la ricerca e i filtri'
@@ -348,14 +353,18 @@ import:
         # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
     worker:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    firefox:
+       page_title: 'Importa da > Firefox'
+       # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    chrome:
+       page_title: 'Importa da > Chrome'
+       # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'Importa da > Instapaper'
+        # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     page_title: 'Sviluppatori'
@@ -382,12 +391,14 @@ developer:
         page_title: 'Sviluppatori > Nuovo client'
         page_description: 'Stai per creare un nuovo client. Compila i campi sottostanti per il redirect URI della tua applicazione.'
         form:
+            # name_label: 'Name of the client'
             redirect_uris_label: 'Redirect URI'
             save_label: 'Crea un nuovo client'
         action_back: 'Indietro'
     client_parameter:
         page_title: 'Sviluppatori > parametri Client'
         page_description: 'Questi sono i tuoi parametri del client.'
+        # field_name: 'Client name'
         field_id: 'Client ID'
         field_secret: 'Client secret'
         back: 'Indietro'
@@ -405,6 +416,33 @@ developer:
             paragraph_8: 'Se vuoi visualizzare tutti gli API endpoints, dai una occhiata alla <a href="%link%">documentazione delle API</a>.'
         back: 'Indietro'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Username'
+        # name_label: 'Name'
+        password_label: 'Password'
+        repeat_new_password_label: 'Ripeti password'
+        plain_password_label: '????'
+        email_label: 'E-mail'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index 6da9ff18acae0612e3d578076a45338e8b168edf..8f06434dba9b3716f1e168cc2d0dc99aa6c54aaa 100644 (file)
@@ -19,18 +19,19 @@ menu:
         unread: 'Pas legits'
         starred: 'Favorits'
         archive: 'Legits'
-        all_articles: 'Tots los articles'
+        all_articles: 'Totes los articles'
         config: 'Configuracion'
         tags: 'Etiquetas'
         internal_settings: 'Configuracion interna'
         import: 'Importar'
         howto: 'Ajuda'
         developer: 'Desvolopador'
-        logout: 'Déconnexion'
+        logout: 'Desconnexion'
         about: 'A prepaus'
         search: 'Cercar'
         save_link: 'Enregistrar un novèl article'
         back_to_unread: 'Tornar als articles pas legits'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Enregistrar un novèl article'
         search: 'Cercar'
@@ -45,9 +46,10 @@ footer:
         social: 'Social'
         powered_by: 'propulsat per'
         about: 'A prepaus'
-    page_title: 'Configuracion'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
+    page_title: 'Configuracion'
     tab_menu:
         settings: 'Paramètres'
         rss: 'RSS'
@@ -72,8 +74,8 @@ config:
     form_rss:
         description: "Los fluxes RSS fornits per wallabag vos permeton de legir vòstres articles salvagardats dins vòstre lector de fluxes preferit. Per los poder emplegar, vos cal, d'en primièr crear un geton."
         token_label: 'Geton RSS'
-        no_token: 'Aucun jeton généré'
-        token_create: 'Pas cap de geton generat'
+        no_token: 'Pas cap de geton generat'
+        token_create: 'Creatz vòstre geton'
         token_reset: 'Reïnicializatz vòstre geton'
         rss_links: 'URL de vòstres fluxes RSS'
         rss_link:
@@ -94,6 +96,7 @@ config:
         if_label: 'se'
         then_tag_as_label: 'alara atribuir las etiquetas'
         delete_rule_label: 'suprimir'
+        # edit_rule_label: 'edit'
         rule_label: 'Règla'
         tags_label: 'Etiquetas'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: "Una règla O l'autra"
                 and: "Una règla E l'autra"
                 matches: 'Teste se un <i>subjècte</i> correspond a una <i>recerca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>'
-    form_new_user:
-        username_label: "Nom d'utilizaire"
-        password_label: 'Senhal'
-        repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
-        plain_password_label: 'Senhal en clar'
-        email_label: 'Adreça de corrièl'
 
 entry:
     page_titles:
@@ -187,7 +184,7 @@ entry:
             re_fetch_content: 'Tornar cargar lo contengut'
             delete: 'Suprimir'
             add_a_tag: 'Ajustar una etiqueta'
-            share_content: 'Partatjar'
+            share_content: 'Partejar'
             share_email_label: 'Corrièl'
             public_link: 'ligam public'
             delete_public_link: 'suprimir lo ligam public'
@@ -224,7 +221,7 @@ about:
         developped_by: 'Desvolopat per'
         website: 'Site web'
         many_contributors: 'E un fum de contributors ♥ <a href="https://github.com/wallabag/wallabag/graphs/contributors">sur Github</a>'
-        project_website: 'Site web del projète'
+        project_website: 'Site web del projècte'
         license: 'Licéncia'
         version: 'Version'
     getting_help:
@@ -245,7 +242,7 @@ about:
 
 howto:
     page_title: 'Ajuda'
-    page_description: "I a mai d'un biai d'enregistrar un article :"
+    page_description: "I a mai d'un biais d'enregistrar un article :"
     top_menu:
         browser_addons: 'Extensions de navigator'
         mobile_apps: 'Aplicacions mobil'
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Per ben començar'
+    # more: 'More…'
     intro:
         title: 'Benvenguda sus wallabag !'
         paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina."
         paragraph_2: 'Seguètz-nos '
     configure:
         title: "Configuratz l'aplicacio"
+        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: "Cambiatz la lenga e l'estil de l'aplicacion"
         rss: 'Activatz los fluxes RSS'
         tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles'
@@ -285,6 +284,7 @@ quickstart:
         import: 'Configurar los impòrt'
     first_steps:
         title: 'Primièrs passes'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'Ajustatz vòstre primièr article'
         unread_articles: 'E racaptatz-lo !'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'Migrar dempuèi wallabag v1'
         wallabag_v2: 'Migrar dempuèi wallabag v2'
         readability: 'Migrar dempuèi Readability'
+        instapaper: 'Migrar dempuèi Instapaper'
     developer:
         title: 'Pels desvolopadors'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Crear vòstra aplicacion tèrça'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Documentacion complèta'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Anotatar vòstre article'
         export: 'Convertissètz vòstres articles en ePub o en PDF'
         search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa"
@@ -344,22 +348,26 @@ import:
         page_title: 'Importar > Wallabag v2'
         description: "Aquesta aisina importarà totas vòstras donadas d'una instància mai de wallabag v2. Anatz dins totes vòstres articles, puèi, sus la barra laterala, clicatz sus \"JSON\". Traparatz un fichièr \"All articles.json\""
     readability:
-        page_title: 'Importer > Readability'
+        page_title: 'Importar > Readability'
         description: "Aquesta aisina importarà totas vòstres articles de Readability. Sus la pagina de l'aisina (https://www.readability.com/tools/), clicatz sus \"Export your data\" dins la seccion \"Data Export\". Recebretz un corrièl per telecargar un json (qu'acaba pas amb un .json de fach)."
         how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar."
     worker:
-        # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+        enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina externa s'ocuparà dels messatges un per un. Lo servici actual es : "
+    firefox:
+        page_title: 'Importar > Firefox'
+        description: "Aquesta aisina importarà totas vòstres favorits de Firefox. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+        how_to: "Mercés de causir lo fichièr de salvagarda e de clicar sul boton dejós per l'importar. Notatz que lo tractament pòt durar un moment ja que totes los articles an d'èsser recuperats."
+    chrome:
+        page_title: 'Importar > Chrome'
+        description: "Aquesta aisina importarà totas vòstres favorits de Chrome. L'emplaçament del fichièr depend de vòstre sistèma operatiu : <ul><li>Sus Linux, anatz al dorsièr <code>~/.config/chromium/Default/</code></li><li>Sus Windows, deu èsser dins <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>sus OS X, deu èsser dins <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Un còp enlà, copiatz lo fichièr de favorits dins un endrech que volètz.<em><br>Notatz que s'avètz Chromium al lòc de Chrome, vos cal cambiar lo camin segon aquesta situacion.</em></p>"
+        how_to: "Mercés de causir lo fichièr de salvagarda e de clicar sul boton dejós per l'importar. Notatz que lo tractament pòt durar un moment ja que totes los articles an d'èsser recuperats."
+    instapaper:
+        page_title: 'Importar > Instapaper'
+        description: "Aquesta aisina importarà totas vòstres articles d'Instapaper. Sus la pagina de paramètres (https://www.instapaper.com/user), clicatz sus \"Download .CSV file\" dins la seccion \"Export\". Un fichièr CSV serà telecargat (aital \"instapaper-export.csv\")."
+        how_to: "Mercés de causir vòstre fichièr Instapaper e de clicar sul boton dejós per lo telecargar e l'importar"
 
 developer:
-    page_title: 'Desvolopador'
+    page_title: 'Desvolopaire'
     welcome_message: "Benvenguda sus l'API de wallabag"
     documentation: 'Documentacion'
     how_to_first_app: 'Cossí crear vòstra primièra aplicacion'
@@ -383,16 +391,18 @@ developer:
         page_title: 'Desvlopador > Novèl client'
         page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion."
         form:
+            name_label: "Nom del client"
             redirect_uris_label: 'URLs de redireccion'
             save_label: 'Crear un novèl client'
         action_back: 'Retorn'
     client_parameter:
         page_title: 'Desvolopador > Los paramètres de vòstre client'
         page_description: 'Vaquí los paramètres de vòstre client'
+        field_name: 'Nom del client'
         field_id: 'ID Client'
         field_secret: 'Clau secreta'
         back: 'Retour'
-        read_howto: 'Legir \"cossí crear ma primièra aplicacion\"'
+        read_howto: 'Legir "cossí crear ma primièra aplicacion"'
     howto:
         page_title: 'Desvolopador > Cossí crear ma primièra aplicacion'
         description:
@@ -406,6 +416,33 @@ developer:
             paragraph_8: "Se volètz totas las adreças d'accès de l'API, donatz un còp d’uèlh <a href=\"%link%\">a la documentacion de l'API</a>."
         back: 'Retorn'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: "Nom d'utilizaire"
+        # name_label: 'Name'
+        password_label: 'Senhal'
+        repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
+        plain_password_label: 'Senhal en clar'
+        email_label: 'Adreça de corrièl'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
@@ -422,10 +459,10 @@ flashes:
         notice:
             entry_already_saved: 'Article ja salvargardat lo %date%'
             entry_saved: 'Article enregistrat'
-            # entry_saved_failed: 'Entry saved but fetching content failed'
+            entry_saved_failed: 'Article salvat mai fracàs de la recuperacion del contengut'
             entry_updated: 'Article mes a jorn'
             entry_reloaded: 'Article recargat'
-            # entry_reload_failed: 'Entry reloaded but fetching content failed'
+            entry_reload_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat"
             entry_archived: 'Article marcat coma legit'
             entry_unarchived: 'Article marcat coma pas legit'
             entry_starred: 'Article apondut dins los favorits'
@@ -439,10 +476,10 @@ flashes:
             failed: "L'importacion a fracassat, mercés de tornar ensajar"
             failed_on_file: "Errorr pendent du tractament de l'import. Mercés de verificar vòstre fichièr."
             summary: "Rapòrt d'import: %imported% importats, %skipped% ja presents."
-            # summary_with_queue: 'Import summary: %queued% queued.'
+            summary_with_queue: "Rapòrt d'import : %queued% en espèra de tractament."
         error:
-            # redis_enabled_not_installed: Redis is enabled for handle asynchronous import but it looks like <u>we can't connect to it</u>. Please check Redis configuration.
-            # rabbit_enabled_not_installed: RabbitMQ is enabled for handle asynchronous import but it looks like <u>we can't connect to it</u>. Please check RabbitMQ configuration.
+            redis_enabled_not_installed: "Redis es capable d'importar de manièra asincròna mai sembla que <u>podèm pas nos conectar amb el</u>. Mercés de verificar la configuracion de Redis."
+            rabbit_enabled_not_installed: "RabbitMQ es capable d'importar de manièra asincròna mai sembla que <u>podèm pas nos conectar amb el</u>. Mercés de verificar la configuracion de RabbitMQ."
     developer:
         notice:
             client_created: 'Novèl client creat'
index f58cd0399da1e55d099fb56a8e2f3970bdf1c114..54e669b31e778c8dfd8cb31c4f780ae0fa2c9f83 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Szukaj'
         save_link: 'Zapisz link'
         back_to_unread: 'Powrót do nieprzeczytanych artykułów'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Dodaj nowy wpis'
         search: 'Szukaj'
@@ -45,6 +46,7 @@ footer:
         social: 'Społeczność'
         powered_by: 'Kontrolowany przez'
         about: 'O nas'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Konfiguracja'
@@ -94,6 +96,7 @@ config:
         if_label: 'jeżeli'
         then_tag_as_label: 'wtedy otaguj jako'
         delete_rule_label: 'usuń'
+        # edit_rule_label: 'edit'
         rule_label: 'Reguła'
         tags_label: 'Tagi'
         faq:
@@ -127,12 +130,6 @@ config:
                 or: 'Jedna reguła LUB inna'
                 and: 'Jedna reguła I inna'
                 matches: 'Sprawdź czy <i>temat</i> pasuje <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł zawiera "piłka nożna"</code>'
-    form_new_user:
-        username_label: 'Nazwa użytkownika'
-        password_label: 'Hasło'
-        repeat_new_password_label: 'Powtórz nowe hasło'
-        plain_password_label: 'Jawne hasło'
-        email_label: 'Adres email'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     page_title: 'Szybki start'
+    # more: 'More…'
     intro:
          title: 'Witaj w wallabag!'
          paragraph_1: "Będziemy ci towarzyszyli w Twojej poznaniu wallabag i pokażemy możliwości, które mogą cię zainteresować."
          paragraph_2: 'Śledź nas!'
     configure:
          title: 'Konfiguruj aplikację'
+         description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
          language: 'Zmień język i wygląd'
          rss: 'Włącz kanały RSS'
          tagging_rules: 'Napisz reguły pozwalające na automatyczne otagowanie twoich artykułów'
@@ -285,6 +284,7 @@ quickstart:
          import: 'Skonfigurować import'
     first_steps:
         title: 'Pierwsze kroki'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link"
         new_article: 'Zapisz swój pierwszy artukuł'
         unread_articles: 'I sklasyfikuj go!'
     migrate:
@@ -294,11 +294,15 @@ quickstart:
         wallabag_v1: 'Migruj z wallabag v1'
         wallabag_v2: 'Migruj z wallabag v2'
         readability: 'Migruj z Readability'
+        instapaper: 'Migruj z Instapaper'
     developer:
         title: 'Deweloperzy'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         create_application: 'Stwórz swoją aplikację'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Pełna Dokumentacja'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         annotate: 'Dadaj adnotację do swojego artykułu'
         export: 'Konwertuj swoje artykuły do ePUB lub PDF'
         search_filters: 'Zabacz jak możesz znaleźć artykuł dzięku użyciu silnika wyszukiwarki i filtrów'
@@ -351,12 +355,16 @@ import:
         enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczęcia importu, zewnętrzna usługa może zajmować się na raz tylko jednym zadaniem. Bieżącą usługą jest:"
     firefox:
        page_title: 'Import > Firefox'
-       description: "Ten importer zaimportuje wszystkie twoje zakładki z Firefoksa. <p>Dla Firefoksa, idź do twoich zakładek (Ctrl+Shift+O), następnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopię zapasową...\". Uzyskasz plik .json."
+       description: "Ten importer zaimportuje wszystkie twoje zakładki z Firefoksa. Idź do twoich zakładek (Ctrl+Shift+O), następnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopię zapasową...\". Uzyskasz plik .json."
        how_to: "Wybierz swój plik z zakładkami i naciśnij poniższy przycisk, aby je zaimportować. Może to zająć dłuższą chwilę, zanim wszystkie artykuły zostaną przeniesione."
     chrome:
        page_title: 'Import > Chrome'
        description: "Ten importer zaimportuje wszystkie twoje zakładki z Chrome. Lokalizacja pliku jest zależna od twojego systemy operacyjnego : <ul><li>Pod Linuksem, idź do katalogu <code>~/.config/chromium/Default/</code></li><li>Pod Windowsem, powinien się on znajdować w <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>Pod OS X, powinien się on znajdować w <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Po odnalezieniu pliku, skopiuj go w łatwo dostęne miejsce.<em><br>Jeżeli używasz Chromium zamiast Chrome, będziesz musiał odpowiednio poprawić ścieżkę dostępu.</em></p>"
        how_to: "Wybierz swój plik z zakładkami i naciśnij poniższy przycisk, aby je zaimportować. Może to zająć dłuższą chwilę, zanim wszystkie artykuły zostaną przeniesione."
+    instapaper:
+        page_title: 'Import > Instapaper'
+        description: 'Ten importer, zaimportuje wszystkie twoje artykuły z Instapaper. W ustawieniach (https://www.instapaper.com/user), kliknij na "Download .CSV file"  w sekcji "Export". Otrzymasz plik CSV.'
+        how_to: 'Wybierz swój plik eksportu z Instapaper i kliknij poniższy przycisk, aby go załadować.'
 
 developer:
     page_title: 'Deweloper'
@@ -366,36 +374,38 @@ developer:
     full_documentation: 'Pokaż pełne API'
     list_methods: 'Lista metod API'
     clients:
-         title: 'Klienci'
-         create_new: 'Utwórz nowego klienta'
+        title: 'Klienci'
+        create_new: 'Utwórz nowego klienta'
     existing_clients:
-         title: 'Istniejący klienci'
-         field_id: 'ID klienta'
-         field_secret: 'Client secret'
-         field_uris: 'Przekieruj URIs'
-         field_grant_types: 'Przyznaj pozwolenie'
-         no_client: 'Nie ma jeszcze klienta.'
+        title: 'Istniejący klienci'
+        field_id: 'ID klienta'
+        field_secret: 'Client secret'
+        field_uris: 'Przekieruj URIs'
+        field_grant_types: 'Przyznaj pozwolenie'
+        no_client: 'Nie ma jeszcze klienta.'
     remove:
-         warn_message_1: 'Masz możliwość usunięcia tego klienta. Ta akcja jest NIEODWRACALNA !'
-         warn_message_2: "Jeżeli go usuniesz, aplikacje skonfigurowane z tym klientem nię będa w stanie autoryzować twojego wallabag."
-         action: 'Usuń tego klienta'
+        warn_message_1: 'Masz możliwość usunięcia tego klienta. Ta akcja jest NIEODWRACALNA !'
+        warn_message_2: "Jeżeli go usuniesz, aplikacje skonfigurowane z tym klientem nię będa w stanie autoryzować twojego wallabag."
+        action: 'Usuń tego klienta'
     client:
-         page_title: 'Deweloper > Nowy klient'
-         page_description: 'Tworzysz nowego klienta. Wypełnij poniższe pole w celu przekierowania URI twojej aplikacji.'
-         form:
-             redirect_uris_label: 'Przekieruj adresy URI'
-             save_label: 'Stwórz nowego klienta'
-         action_back: 'Cofnij'
+        page_title: 'Deweloper > Nowy klient'
+        page_description: 'Tworzysz nowego klienta. Wypełnij poniższe pole w celu przekierowania URI twojej aplikacji.'
+        form:
+            # name_label: 'Name of the client'
+            redirect_uris_label: 'Przekieruj adresy URI'
+            save_label: 'Stwórz nowego klienta'
+        action_back: 'Cofnij'
     client_parameter:
-         page_title: 'Deweloper > Parametry klienta'
-         page_description: 'Tutaj znajdują się parametry klienta.'
-         field_id: 'Client ID'
-         field_secret: 'Client secret'
-         back: 'Cofnij'
-         read_howto: 'Przeczytaj jak "Stworzyć moją pierwszą aplikację"'
+        page_title: 'Deweloper > Parametry klienta'
+        page_description: 'Tutaj znajdują się parametry klienta.'
+        # field_name: 'Client name'
+        field_id: 'Client ID'
+        field_secret: 'Client secret'
+        back: 'Cofnij'
+        read_howto: 'Przeczytaj jak "Stworzyć moją pierwszą aplikację"'
     howto:
-         page_title: 'Deweloper > Jak stworzyć moją pierwszą aplikację'
-         description:
+        page_title: 'Deweloper > Jak stworzyć moją pierwszą aplikację'
+        description:
             paragraph_1: 'Następujące komendy korzystają <a href="https://github.com/jkbrzt/httpie">Biblioteka HTTPie</a>. Upewnij się, czy zainstalowałeś ją w swoim systemie zanim z niej skorzystasz'
             paragraph_2: 'Potrzebujesz tokena w celu nawiązania komunikacji między swoją aplikacją a API wallabag.'
             paragraph_3: 'W celu stworzenia tokena musisz <a href="%link%">stwórz nowego klienta</a>.'
@@ -404,7 +414,34 @@ developer:
             paragraph_6: 'access_token jest użyteczny do wywołania API endpoint. Na przykład:'
             paragraph_7: 'To wywołanie zwróci wszystkie twoje wpisy.'
             paragraph_8: 'Jeżeli chcesz wyświetlić wszystkie punkty końcowe API, zobacz <a href="%link%">Dokumentacja naszego API</a>.'
-         back: 'Cofnij'
+        back: 'Cofnij'
+
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Nazwa użytkownika'
+        # name_label: 'Name'
+        password_label: 'Hasło'
+        repeat_new_password_label: 'Powtórz nowe hasło'
+        plain_password_label: 'Jawne hasło'
+        email_label: 'Adres email'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
 
 flashes:
     config:
index 067f78786b6027efb9097e18bbef425e1ec2d275..4e0e454c18e6175cb5b904441d6e4a773043ae81 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Căutare'
         # save_link: 'Save a link'
         back_to_unread: 'Înapoi la articolele necitite'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Introdu un nou articol'
         search: 'Căutare'
@@ -45,6 +46,7 @@ footer:
         # social: 'Social'
         # powered_by: 'powered by'
         about: 'Despre'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Configurație'
@@ -94,6 +96,7 @@ config:
         # if_label: 'if'
         # then_tag_as_label: 'then tag as'
         # delete_rule_label: 'delete'
+        # edit_rule_label: 'edit'
         # rule_label: 'Rule'
         # tags_label: 'Tags'
         # faq:
@@ -127,12 +130,6 @@ config:
         #         or: 'One rule OR another'
         #         and: 'One rule AND another'
         #         matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
-    form_new_user:
-        username_label: 'Nume de utilizator'
-        password_label: 'Parolă'
-        repeat_new_password_label: 'Repeat new password'
-        plain_password_label: '????'
-        email_label: 'E-mail'
 
 entry:
     page_titles:
@@ -266,12 +263,14 @@ howto:
 
 quickstart:
     # page_title: 'Quickstart'
+    # more: 'More…'
     # intro:
     #     title: 'Welcome to wallabag!'
     #     paragraph_1: "We'll accompany you to visit wallabag and show you some features which can interest you."
     #     paragraph_2: 'Follow us!'
     # configure:
     #     title: 'Configure the application'
+    #     description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
     #     language: 'Change language and design'
     #     rss: 'Enable RSS feeds'
     #     tagging_rules: 'Write rules to automatically tag your articles'
@@ -285,6 +284,7 @@ quickstart:
     #     import: 'Configure import'
     # first_steps:
     #     title: 'First steps'
+    #     description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
     #     new_article: 'Save your first article'
     #     unread_articles: 'And classify it!'
     # migrate:
@@ -294,11 +294,15 @@ quickstart:
     #     wallabag_v1: 'Migrate from wallabag v1'
     #     wallabag_v2: 'Migrate from wallabag v2'
     #     readability: 'Migrate from Readability'
+    #     instapaper: 'Migrate from Instapaper'
     # developer:
     #     title: 'Developers'
+    #     description: 'We also thought to the developers: Docker, API, translations, etc.'
     #     create_application: 'Create your third application'
+    #     use_docker: 'Use Docker to install wallabag'
     # docs:
     #     title: 'Full documentation'
+    #     description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
     #     annotate: 'Annotate your article'
     #     export: 'Convert your articles into ePUB or PDF'
     #     search_filters: 'See how you can look for an article by using search engine and filters'
@@ -351,12 +355,16 @@ import:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
     # firefox:
     #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+    #    description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
     #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
     # chrome:
     #    page_title: 'Import > Chrome'
     #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
     #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    # instapaper:
+    #     page_title: 'Import > Instapaper'
+    #     description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+    #     how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     # page_title: 'Developer'
@@ -383,12 +391,14 @@ developer:
     #     page_title: 'Developer > New client'
     #     page_description: 'You are about to create a new client. Please fill the field below for the redirect URI of your application.'
     #     form:
+    #         name_label: 'Name of the client'
     #         redirect_uris_label: 'Redirect URIs'
     #         save_label: 'Create a new client'
     #     action_back: 'Back'
     # client_parameter:
     #     page_title: 'Developer > Client parameters'
     #     page_description: 'Here are your client parameters.'
+    #     field_name: 'Client name'
     #     field_id: 'Client ID'
     #     field_secret: 'Client secret'
     #     back: 'Back'
@@ -406,6 +416,33 @@ developer:
     #         paragraph_8: 'If you want to see all the API endpoints, you can have a look <a href="%link%">to our API documentation</a>.'
     #     back: 'Back'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Nume de utilizator'
+        # name_label: 'Name'
+        password_label: 'Parolă'
+        repeat_new_password_label: 'Repeat new password'
+        plain_password_label: '????'
+        email_label: 'E-mail'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index 62c69510317cced07131ffcfd704a17a45c9d1b2..02b3aae62fc25e7aecc3b0c67954c64c1540b994 100644 (file)
@@ -31,6 +31,7 @@ menu:
         search: 'Ara'
         # save_link: 'Save a link'
         back_to_unread: 'Okunmayan makalelere geri dön'
+        # users_management: 'Users management'
     top:
         add_new_entry: 'Yeni bir makale ekle'
         search: 'Ara'
@@ -45,6 +46,7 @@ footer:
         social: 'Sosyal'
         powered_by: 'powered by'
         about: 'Hakkımızda'
+    # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
 
 config:
     page_title: 'Yapılandırma'
@@ -127,12 +129,6 @@ config:
                 or: 'Bir kural veya birbaşkası'
                 and: 'Bir kural ve diğeri'
                 # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
-    form_new_user:
-        username_label: 'Kullanıcı adı'
-        password_label: 'Şifre'
-        repeat_new_password_label: 'Yeni şifrenin tekrarı'
-        plain_password_label: '????'
-        email_label: 'E-posta'
 
 entry:
     page_titles:
@@ -266,12 +262,14 @@ howto:
 
 quickstart:
     page_title: 'Hızlı başlangıç'
+    # more: 'More…'
     intro:
         title: 'wallabag'
         paragraph_1: "wallabag kurduğunuz için teşekkür ederiz. Bu sayfada biz size eşlik edecek ve ilginizi çekecek birkaç özellik göstereceğim."
         paragraph_2: 'Bizi takip edin!'
     configure:
         title: 'Uygulamayı Yapılandırma'
+        # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
         language: 'Dili ve tasarımı değiştirme'
         rss: 'RSS akışını aktifleştirme'
         # tagging_rules: 'Write rules to automatically tag your articles'
@@ -285,6 +283,7 @@ quickstart:
         # import: 'Configure import'
     first_steps:
         title: 'İlk adım'
+        # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
         new_article: 'İlk makalenizi kaydedin'
         unread_articles: 'Ve bunu sınıflandırın!'
     migrate:
@@ -294,11 +293,15 @@ quickstart:
         wallabag_v1: "wallabag v1 üzerindeki verilerinizi wallabag'in yeni sürümüne aktarın"
         wallabag_v2: "wallabag v2 üzerindeki verilerinizi wallabag'in yeni sürümüne aktarın"
         readability: "Readability üzerindeki verilerinizi wallabag'e aktarın'"
+        instapaper: "Instapaper üzerindeki verilerinizi wallabag'e aktarın'"
     developer:
         # title: 'Developers'
+        # description: 'We also thought to the developers: Docker, API, translations, etc.'
         # create_application: 'Create your third application'
+        # use_docker: 'Use Docker to install wallabag'
     docs:
         title: 'Dokümantasyon'
+        # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
         # annotate: 'Annotate your article'
         export: 'Makalelerinizi ePUB ya da PDF formatına çevirme'
         search_filters: 'Makaleleri görüntülemek için arama motorlarını ve filteri kullanma'
@@ -349,14 +352,18 @@ import:
         # how_to: 'Please select your Readability export and click on the below button to upload and import it.'
     worker:
         # enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
-    # firefox:
-    #    page_title: 'Import > Firefox'
-    #    description: "This importer will import all your Firefox bookmarks. <p>For Firefox, just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
-    # chrome:
-    #    page_title: 'Import > Chrome'
-    #    description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
-    #    how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    firefox:
+       page_title: 'İçe Aktar > Firefox'
+       # description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    chrome:
+       page_title: 'İçe Aktar > Chrome'
+       # description: "This importer will import all your Chrome bookmarks. The location of the file depends on your operating system : <ul><li>On Linux, go into the <code>~/.config/chromium/Default/</code> directory</li><li>On Windows, it should be at <code>%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default</code></li><li>On OS X, it should be at <code>~/Library/Application Support/Google/Chrome/Default/Bookmarks</code></li></ul>Once you got there, copy the Bookmarks file someplace you'll find.<em><br>Note that if you have Chromium instead of Chrome, you'll have to correct paths accordingly.</em></p>"
+       # how_to: "Please choose the bookmark backup file and click on the button below to import it. Note that the process may take a long time since all articles have to be fetched."
+    instapaper:
+        page_title: 'İçe Aktar > Instapaper'
+        # description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
+        # how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
 
 developer:
     # page_title: 'Developer'
@@ -383,12 +390,14 @@ developer:
     #     page_title: 'Developer > New client'
     #     page_description: 'You are about to create a new client. Please fill the field below for the redirect URI of your application.'
     #     form:
+    #        name_label: 'Name of the client'
     #         redirect_uris_label: 'Redirect URIs'
     #         save_label: 'Create a new client'
     #     action_back: 'Back'
     # client_parameter:
     #     page_title: 'Developer > Client parameters'
     #     page_description: 'Here are your client parameters.'
+    #     field_name: 'Client name'
     #     field_id: 'Client ID'
     #     field_secret: 'Client secret'
     #     back: 'Back'
@@ -406,6 +415,33 @@ developer:
     #         paragraph_8: 'If you want to see all the API endpoints, you can have a look <a href="%link%">to our API documentation</a>.'
     #     back: 'Back'
 
+user:
+    # page_title: Users management
+    # new_user: Create a new user
+    # edit_user: Edit an existing user
+    # description: "Here you can manage all users (create, edit and delete)"
+    # list:
+    #     actions: Actions
+    #     edit_action: Edit
+    #     yes: Yes
+    #     no: No
+    #     create_new_one: Create a new user
+    form:
+        username_label: 'Kullanıcı adı'
+        # name_label: 'Name'
+        password_label: 'Şifre'
+        repeat_new_password_label: 'Yeni şifrenin tekrarı'
+        plain_password_label: '????'
+        email_label: 'E-posta'
+        # enabled_label: 'Enabled'
+        # locked_label: 'Locked'
+        # last_login_label: 'Last login'
+        # twofactor_label: Two factor authentication
+        # save: Save
+        # delete: Delete
+        # delete_confirm: Are you sure?
+        # back_to_list: Back to list
+
 flashes:
     config:
         notice:
index dfe2c64d40907be25568d4c510115868986fb33c..313339ed0c0b861699cda30f605562706d30a8ef 100644 (file)
@@ -1,6 +1,6 @@
 validator:
     password_must_match: 'De indtastede adgangskoder skal være ens'
     password_too_short: 'Adgangskoden skal være mindst 8 tegn'
-#     password_wrong_value: 'Wrong value for your current password'
-#     item_per_page_too_high: 'This will certainly kill the app'
-#     rss_limit_too_hight: 'This will certainly kill the app'
+    # password_wrong_value: 'Wrong value for your current password'
+    # item_per_page_too_high: 'This will certainly kill the app'
+    # rss_limit_too_hight: 'This will certainly kill the app'
index 80ab470afc3483265c0c872efbe108d85c922e7e..1b358965de256f1b07e8890b169caba1084f2bd8 100644 (file)
@@ -1,6 +1,6 @@
 validator:
-#     password_must_match: 'The password fields must match.'
-#     password_too_short: 'Password should by at least 8 chars long'
-#     password_wrong_value: 'Wrong value for your current password'
-#     item_per_page_too_high: 'This will certainly kill the app'
-#     rss_limit_too_hight: 'This will certainly kill the app'
+    # password_must_match: 'The password fields must match.'
+    # password_too_short: 'Password should by at least 8 chars long'
+    # password_wrong_value: 'Wrong value for your current password'
+    # item_per_page_too_high: 'This will certainly kill the app'
+    # rss_limit_too_hight: 'This will certainly kill the app'
index 0f88901a5c0102cfaf10eba2b000711452d97f12..a1a9a1368949178e9d649fe92f7a3e3348bd58c7 100644 (file)
@@ -43,7 +43,7 @@
             {% block scripts %}
             {% endblock %}
 
-            <title>wallabag - {% block title %}{% endblock %}</title>
+            <title>{% block title %}{% endblock %} – wallabag</title>
         {% endblock %}
     </head>
 
index 6446cf2c33823d2f5fd724fa454bcb7b5dbaa37a..ff7ef73a81509ac971aac10e47061aecc611b9b6 100644 (file)
             « {{ tagging_rule.rule }} »
             {{ 'config.form_rules.then_tag_as_label'|trans }}
             « {{ tagging_rule.tags|join(', ') }} »
+            <a href="{{ path('edit_tagging_rule', {id: tagging_rule.id}) }}" title="{{ 'config.form_rules.edit_rule_label'|trans }}" class="tool mode_edit">✎</a>
             <a href="{{ path('delete_tagging_rule', {id: tagging_rule.id}) }}" title="{{ 'config.form_rules.delete_rule_label'|trans }}" class="tool delete icon-trash icon"></a>
         </li>
         {% endfor %}
             </table>
         </div>
     </div>
-
-    {% if is_granted('ROLE_SUPER_ADMIN') %}
-    <h2>{{ 'config.tab_menu.new_user'|trans }}</h2>
-
-    {{ form_start(form.new_user) }}
-        {{ form_errors(form.new_user) }}
-
-        <fieldset class="w500p inline">
-            <div class="row">
-                {{ form_label(form.new_user.username) }}
-                {{ form_errors(form.new_user.username) }}
-                {{ form_widget(form.new_user.username) }}
-            </div>
-        </fieldset>
-
-        <fieldset class="w500p inline">
-            <div class="row">
-                {{ form_label(form.new_user.plainPassword.first) }}
-                {{ form_errors(form.new_user.plainPassword.first) }}
-                {{ form_widget(form.new_user.plainPassword.first) }}
-            </div>
-        </fieldset>
-
-        <fieldset class="w500p inline">
-            <div class="row">
-                {{ form_label(form.new_user.plainPassword.second) }}
-                {{ form_errors(form.new_user.plainPassword.second) }}
-                {{ form_widget(form.new_user.plainPassword.second) }}
-            </div>
-        </fieldset>
-
-        <fieldset class="w500p inline">
-            <div class="row">
-                {{ form_label(form.new_user.email) }}
-                {{ form_errors(form.new_user.email) }}
-                {{ form_widget(form.new_user.email) }}
-            </div>
-        </fieldset>
-
-        {{ form_rest(form.new_user) }}
-        {% endif %}
-    </form>
 {% endblock %}
index 8d841b4cf477cb02c95c7f01c0b4e5e32471364b..1c0430e8a8357f60a86ecefdb2dd915e80517ca9 100644 (file)
@@ -1,7 +1,7 @@
 {% extends "WallabagCoreBundle::layout.html.twig" %}
 
 {% block title %}
-    {% include "@WallabagCore/themes/_title.html.twig" %}
+    {% include "@WallabagCore/themes/common/Entry/_title.html.twig" %}
 {% endblock %}
 
 {% block content %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Exception/error.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Exception/error.html.twig
new file mode 100644 (file)
index 0000000..b52634f
--- /dev/null
@@ -0,0 +1,24 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'error.page_title'|trans }}{% endblock %}
+
+{% block body_class %}login{% endblock %}
+
+{% block menu %}{% endblock %}
+{% block messages %}{% endblock %}
+{% block header %}{% endblock %}
+
+{% block content %}
+<main class="valign-wrapper">
+    <div class="valign row">
+        <div class="card sw">
+            <div class="center"><img src="{{ asset('bundles/wallabagcore/themes/_global/img/logo-w.png') }}" alt="wallabag logo" /></div>
+            <h2>{{ status_code }}: {{ status_text }}</h2>
+            <p>{{ exception.message }}</p>
+        </div>
+    </div>
+</main>
+{% endblock %}
+
+{% block footer %}
+{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/about.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/about.html.twig
deleted file mode 100644 (file)
index 918249d..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'about.page_title'|trans }}{% endblock %}
-
-{% block content %}
-    <h2>{{ 'about.top_menu.who_behind_wallabag'|trans }}</h2>
-
-    <dl>
-        <dt>{{ 'about.who_behind_wallabag.developped_by'|trans }}</dt>
-        <dd><a href="mailto:nicolas@loeuillet.org">Nicolas Lœuillet</a> — <a href="http://www.loeuillet.org">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
-        <dd>Thomas Citharel — <a href="https://tcit.fr">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
-        <dd>Jérémy Benoist — <a href="http://www.j0k3r.net">{{ 'about.who_behind_wallabag.website'|trans }}</a></dd>
-
-        <dt>{{ 'about.who_behind_wallabag.many_contributors'|trans|raw }}</dt>
-
-        <dt>{{ 'about.who_behind_wallabag.project_website'|trans }}</dt>
-        <dd><a href="https://www.wallabag.org">https://www.wallabag.org</a></dd>
-
-        <dt>{{ 'about.who_behind_wallabag.license'|trans }}: <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a></dt>
-
-        <dt>{{ 'about.who_behind_wallabag.version'|trans }}: {{ version }}</dt>
-    </dl>
-
-    <h2>{{ 'about.top_menu.getting_help'|trans }}</h2>
-
-    <dl>
-        <dt>{{ 'about.getting_help.documentation'|trans }}</dt>
-        <dd><a href="http://doc.wallabag.org/en/master/">english</a></dd>
-        <dd><a href="http://doc.wallabag.org/fr/master/">français</a></dd>
-
-        <dt>{{ 'about.getting_help.bug_reports'|trans }}</dt>
-        <dd>{{ 'about.getting_help.support'|trans|raw }}</dd>
-    </dl>
-
-    <h2>{{ 'about.top_menu.helping'|trans }}</h2>
-
-    <p>{{ 'about.helping.description'|trans }}</p>
-
-    <dl>
-        <dd>{{ 'about.helping.by_contributing_2'|trans }} <a href="https://github.com/wallabag/wallabag/issues/1254">{{ 'about.helping.by_contributing'|trans }}</a></dd>
-        <dd><a href="{{ paypal_url }}">{{ 'about.helping.by_paypal'|trans }}</a></dd>
-    </dl>
-
-    <h2>{{ 'about.top_menu.contributors'|trans }}</h2>
-    <p><a href="https://github.com/wallabag/wallabag/graphs/contributors">{{ 'about.contributors.description'|trans }}</a></p>
-
-    <h2>{{ 'about.top_menu.third_party'|trans }}</h2>
-    <p>{{ 'about.third_party.description'|trans }}</p>
-    <table class="striped">
-        <tr>
-            <th>{{ 'about.third_party.package'|trans }}</th>
-            <th>{{ 'about.third_party.license'|trans }}</th>
-        </tr>
-        <tr><td>behat/transliterator</td><td>Artistic 1.0</td></tr>
-        <tr><td>CraueConfigBundle</td><td>MIT</td></tr>
-        <tr><td>doctrine/annotations</td><td>MIT</td></tr>
-        <tr><td>doctrine/cache</td><td>MIT</td></tr>
-        <tr><td>doctrine/collections</td><td>MIT</td></tr>
-        <tr><td>doctrine/common</td><td>MIT</td></tr>
-        <tr><td>doctrine/dbal</td><td>MIT</td></tr>
-        <tr><td>doctrine/doctrine-bundle</td><td>MIT</td></tr>
-        <tr><td>doctrine/doctrine-cache-bundle</td><td>MIT</td></tr>
-        <tr><td>doctrine/doctrine-migrations-bundle</td><td>MIT</td></tr>
-        <tr><td>doctrine/inflector</td><td>MIT</td></tr>
-        <tr><td>doctrine/instantiator</td><td>MIT</td></tr>
-        <tr><td>doctrine/lexer</td><td>MIT</td></tr>
-        <tr><td>doctrine/migrations</td><td>LGPL-2.1</td></tr>
-        <tr><td>doctrine/orm</td><td>MIT</td></tr>
-        <tr><td>friendsofsymfony/oauth-server-bundle</td><td>MIT</td></tr>
-        <tr><td>friendsofsymfony/oauth2-php</td><td>MIT</td></tr>
-        <tr><td>friendsofsymfony/rest-bundle</td><td>MIT</td></tr>
-        <tr><td>friendsofsymfony/user-bundle</td><td>MIT</td></tr>
-        <tr><td>gedmo/doctrine-extensions</td><td>MIT</td></tr>
-        <tr><td>grandt/binstring</td><td>LGPL-2.1</td></tr>
-        <tr><td>grandt/phpepub</td><td>LGPL-2.1</td></tr>
-        <tr><td>grandt/phpresizegif</td><td>LGPL-2.1</td></tr>
-        <tr><td>grandt/phpzipmerge</td><td>LGPL-2.1</td></tr>
-        <tr><td>grandt/relativepath</td><td>LGPL-2.1</td></tr>
-        <tr><td>guzzlehttp/guzzle</td><td>MIT</td></tr>
-        <tr><td>guzzlehttp/ringphp</td><td>MIT</td></tr>
-        <tr><td>guzzlehttp/streams</td><td>MIT</td></tr>
-        <tr><td>hoa/compiler</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/consistency</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/event</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/exception</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/file</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/iterator</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/math</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/protocol</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/regex</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/ruler</td><td>BSD-3-Clausev
-        <tr><td>hoa/stream</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/ustring</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/visitor</td><td>BSD-3-Clause</td></tr>
-        <tr><td>hoa/zformat</td><td>BSD-3-Clause</td></tr>
-        <tr><td>htmlawed/htmlawed</td><td>GPL-2.0+ or LGPL-3.0</td></tr>
-        <tr><td>incenteev/composer-parameter-handler</td><td>MIT</td></tr>
-        <tr><td>j0k3r/graby</td><td>AGPL-3.0</td></tr>
-        <tr><td>j0k3r/graby-site-config</td><td>AGPL-3.0</td></tr>
-        <tr><td>j0k3r/php-readability</td><td>Apache-2.0</td></tr>
-        <tr><td>j0k3r/safecurl</td><td>MIT</td></tr>
-        <tr><td>jdorn/sql-formatter</td><td>MIT</td></tr>
-        <tr><td>jms/metadata</td><td>Apache</td></tr>
-        <tr><td>jms/parser-lib</td><td>Apache2</td></tr>
-        <tr><td>jms/serializer</td><td>Apache2</td></tr>
-        <tr><td>jms/serializer-bundle</td><td>Apache2</td></tr>
-        <tr><td>kphoen/rulerz</td><td>MIT</td></tr>
-        <tr><td>kphoen/rulerz-bundle</td><td>MIT</td></tr>
-        <tr><td>kriswallsmith/assetic</td><td>MIT</td></tr>
-        <tr><td>lexik/form-filter-bundle</td><td>MIT</td></tr>
-        <tr><td>liip/theme-bundle</td><td>MIT</td></tr>
-        <tr><td>mgargano/simplehtmldom</td><td>MIT</td></tr>
-        <tr><td>michelf/php-markdown</td><td>BSD-3-Clause</td></tr>
-        <tr><td>monolog/monolog</td><td>MIT</td></tr>
-        <tr><td>neitanod/forceutf8</td><td>BSD-3-Clause</td></tr>
-        <tr><td>nelmio/api-doc-bundle</td><td>MIT</td></tr>
-        <tr><td>nelmio/cors-bundle</td><td>MIT</td></tr>
-        <tr><td>ocramius/proxy-manager</td><td>MIT</td></tr>
-        <tr><td>pagerfanta/pagerfanta</td><td>MIT</td></tr>
-        <tr><td>paragonie/random_compat</td><td>MIT</td></tr>
-        <tr><td>phpcollection/phpcollection</td><td>Apache2</td></tr>
-        <tr><td>phpoption/phpoption</td><td>Apache2</td></tr>
-        <tr><td>phpzip/phpzip</td><td>LGPL-2.1</td></tr>
-        <tr><td>psr/log</td><td>MIT</td></tr>
-        <tr><td>react/promise</td><td>MIT</td></tr>
-        <tr><td>scheb/two-factor-bundle</td><td>MIT</td></tr>
-        <tr><td>sensio/distribution-bundle</td><td>MIT</td></tr>
-        <tr><td>sensio/framework-extra-bundle</td><td>MIT</td></tr>
-        <tr><td>sensiolabs/security-checker</td><td>MIT</td></tr>
-        <tr><td>simplepie/simplepie</td><td>BSD-3-Clause</td></tr>
-        <tr><td>smalot/pdfparser</td><td>GPL-3.0</td></tr>
-        <tr><td>sonata-project/google-authenticator</td><td>MIT</td></tr>
-        <tr><td>stof/doctrine-extensions-bundle</td><td>MIT</td></tr>
-        <tr><td>swiftmailer/swiftmailer</td><td>MIT</td></tr>
-        <tr><td>symfony/assetic-bundle</td><td>MIT</td></tr>
-        <tr><td>symfony/monolog-bundle</td><td>MIT</td></tr>
-        <tr><td>All of Symfony</td><td>MIT-licenced</td></tr>
-        <tr><td>tecnickcom/tcpdf</td><td>LGPLv3</td></tr>
-        <tr><td>twig/extensions</td><td>MIT</td></tr>
-        <tr><td>twig/twig</td><td>BSD-3-Clause</td></tr>
-        <tr><td>wallabag/php-mobi</td><td>Apache-2.0</td></tr>
-        <tr><td>willdurand/hateoas</td><td>MIT</td></tr>
-        <tr><td>willdurand/hateoas-bundle</td><td>MIT</td></tr>
-        <tr><td>willdurand/jsonp-callback-validator</td><td>MIT</td></tr>
-        <tr><td>willdurand/negotiation</td><td>MIT</td></tr>
-        <tr><td>zendframework/zend-code</td><td>BSD-3-Clause</td></tr>
-        <tr><td>zendframework/zend-eventmanager</td><td>BSD-3-Clause</td></tr>
-        <tr><td>doctrine/data-fixtures</td><td>MIT</td></tr>
-        <tr><td>doctrine/doctrine-fixtures-bundle</td><td>MIT</td></tr>
-        <tr><td>phpdocumentor/reflection-docblock</td><td>MIT</td></tr>
-        <tr><td>phpspec/prophecy</td><td>MIT</td></tr>
-        <tr><td>phpunit/php-code-coverage</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/php-file-iterator</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/php-text-template</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/php-timer</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/php-token-stream</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/phpunit</td><td>BSD-3-Clause</td></tr>
-        <tr><td>phpunit/phpunit-mock-objects</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/comparator</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/diff</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/environment</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/exporter</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/global-state</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/recursion-context</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sebastian/version</td><td>BSD-3-Clause</td></tr>
-        <tr><td>sensio/generator-bundle</td><td>MIT</td></tr>
-        <tr><td>symfony/phpunit-bridge</td><td>MIT</td></tr>
-    </table>
-{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/howto.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/howto.html.twig
deleted file mode 100644 (file)
index b529a0a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'howto.page_title'|trans }}{% endblock %}
-
-{% block content %}
-    <h2>{{ 'howto.page_title'|trans }}</h2>
-
-    <p>{{ 'howto.page_description'|trans }}</p>
-    <ul>
-        <li><a href="{{ path('new') }}">{{ 'howto.form.description'|trans }}</a></li>
-    </ul>
-    <h3>{{ 'howto.top_menu.browser_addons'|trans }}</h3>
-    <ul>
-        <li><a href="{{ addonsUrl.firefox }}" target="_blank">{{ 'howto.browser_addons.firefox'|trans }}</a></li>
-        <li><a href="{{ addonsUrl.chrome }}" target="_blank">{{ 'howto.browser_addons.chrome'|trans }}</a></li>
-    </ul>
-    <h3>{{ 'howto.top_menu.mobile_apps'|trans }}</h3>
-    <ul>
-        <li>Android: <a href="{{ addonsUrl.f_droid }}" target="_blank">{{ 'howto.mobile_apps.android.via_f_droid'|trans }}</a> / <a href="{{ addonsUrl.google_play }}" target="_blank">{{ 'howto.mobile_apps.android.via_google_play'|trans }}</a></li>
-        <li>iOS: <a href="{{ addonsUrl.ios }}" target="_blank">{{ 'howto.mobile_apps.ios'|trans }}</a></li>
-        <li>Windows Phone: <a href="{{ addonsUrl.windows }}" target="_blank">{{ 'howto.mobile_apps.windows'|trans }}</a></li>
-    </ul>
-    <h3>{{ 'howto.top_menu.bookmarklet'|trans }}</h3>
-    <p>
-    {{ 'howto.bookmarklet.description'|trans }}
-    {% include 'WallabagCoreBundle::_bookmarklet.html.twig' %}
-
-{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/quickstart.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Static/quickstart.html.twig
deleted file mode 100644 (file)
index ea1c1cb..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'quickstart.page_title'|trans }}{% endblock %}
-
-{% block content %}
-
-    <h3>{{ 'quickstart.intro.title'|trans }}</h3>
-    <p>{{ 'quickstart.intro.paragraph_1'|trans }}</p>
-    <p>{{ 'quickstart.intro.paragraph_2'|trans }}</p>
-
-    <h4>{{ 'quickstart.configure.title'|trans }}</h4>
-    <ul>
-        <li><a href="{{ path('config') }}">{{ 'quickstart.configure.language'|trans }}</a></li>
-        <li><a href="{{ path('config') }}#set2">{{ 'quickstart.configure.rss'|trans }}</a></li>
-        <li><a href="{{ path('config') }}#set5">{{ 'quickstart.configure.tagging_rules'|trans }}</a></li>
-    </ul>
-
-    {% if is_granted('ROLE_SUPER_ADMIN') %}
-    <h4>{{ 'quickstart.admin.title'|trans }}</h4>
-    <p>{{ 'quickstart.admin.description'|trans }}</p>
-    <ul>
-        <li><a href="{{ path('config') }}#set6">{{ 'quickstart.admin.new_user'|trans }}</a></li>
-        <li><a href="{{ path('craue_config_settings_modify') }}#set-analytics">{{ 'quickstart.admin.analytics'|trans }}</a></li>
-        <li><a href="{{ path('craue_config_settings_modify') }}#set-entry">{{ 'quickstart.admin.sharing'|trans }}</a></li>
-        <li><a href="{{ path('craue_config_settings_modify') }}#set-export">{{ 'quickstart.admin.export'|trans }}</a></li>
-        <li><a href="{{ path('craue_config_settings_modify') }}#set-import">{{ 'quickstart.admin.import'|trans }}</a></li>
-    </ul>
-    {% endif %}
-
-    <h4>{{ 'quickstart.first_steps.title'|trans }}</h4>
-    <ul>
-        <li><a href="{{ path('new') }}">{{ 'quickstart.first_steps.new_article'|trans }}</a></li>
-        <li><a href="{{ path('unread') }}">{{ 'quickstart.first_steps.unread_articles'|trans }}</a></li>
-    </ul>
-
-    <h4>{{ 'quickstart.migrate.title'|trans }}</h4>
-    <p>{{ 'quickstart.migrate.description'|trans }}</p>
-    <ul>
-        <li><a href="{{ path('import_pocket') }}">{{ 'quickstart.migrate.pocket'|trans }}</a></li>
-        <li><a href="{{ path('import_wallabag_v1') }}">{{ 'quickstart.migrate.wallabag_v1'|trans }}</a></li>
-        <li><a href="{{ path('import_wallabag_v2') }}">{{ 'quickstart.migrate.wallabag_v2'|trans }}</a></li>
-        <li><a href="{{ path('import_readability') }}">{{ 'quickstart.migrate.readability'|trans }}</a></li>
-    </ul>
-
-    <h4>{{ 'quickstart.developer.title'|trans }}</h4>
-    <ul>
-        <li><a href="{{ path('developer') }}">{{ 'quickstart.developer.create_application'|trans }}</a></li>
-    </ul>
-
-    <h4>{{ 'quickstart.docs.title'|trans }}</h4>
-    <ul>
-        <li><a href="http://doc.wallabag.org/en/master/user/annotations.html">{{ 'quickstart.docs.annotate'|trans }}</a></li>
-        <li><a href="http://doc.wallabag.org/en/master/user/download_articles.html">{{ 'quickstart.docs.export'|trans }}</a></li>
-        <li><a href="http://doc.wallabag.org/en/master/user/filters.html">{{ 'quickstart.docs.search_filters'|trans }}</a></li>
-        <li><a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html">{{ 'quickstart.docs.fetching_errors'|trans }}</a></li>
-        <li><a href="http://doc.wallabag.org/">{{ 'quickstart.docs.all_docs'|trans }}</a></li>
-    </ul>
-
-    <h4>{{ 'quickstart.support.title'|trans }}</h4>
-    <p>{{ 'quickstart.support.description'|trans }}</p>
-    <ul>
-        <li><a href="https://github.com/wallabag/wallabag/issues/">{{ 'quickstart.support.github'|trans }}</a></li>
-        <li><a href="mailto:hello@wallabag.org">{{ 'quickstart.support.email'|trans }}</a></li>
-        <li><a href="https://gitter.im/wallabag/wallabag">{{ 'quickstart.support.gitter'|trans }}</a></li>
-    </ul>
-
-{% endblock %}
index 4fd4d317afb183558f37674bf21d39ef29b5957f..30fd0d85a3cd302d6fe11233a0151d940aaef8a7 100644 (file)
@@ -42,6 +42,7 @@
         </li>-->
         <li><a href="{{ path('config') }}">{{ 'menu.left.config'|trans }}</a></li>
         {% if is_granted('ROLE_SUPER_ADMIN') %}
+            <li><a href="{{ path('user_index') }}">{{ 'menu.left.users_management'|trans }}</a></li>
             <li><a href="{{ path('craue_config_settings_modify') }}">{{ 'menu.left.internal_settings'|trans }}</a></li>
         {% endif %}
         <li><a href="{{ path('import') }}">{{ 'menu.left.import'|trans }}</a></li>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Mail/forgotPassword.txt.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Mail/forgotPassword.txt.twig
new file mode 100644 (file)
index 0000000..631bcb8
--- /dev/null
@@ -0,0 +1,6 @@
+Hello {{username}}!
+
+To reset your password - please visit {{confirmationUrl}}
+
+Regards,
+Wallabag bot
similarity index 95%
rename from src/Wallabag/CoreBundle/Resources/views/themes/material/Static/howto.html.twig
rename to src/Wallabag/CoreBundle/Resources/views/themes/common/Static/howto.html.twig
index 6a177d6bbaa7e2feb822b54b6988b567f3264d52..67a101900cd015653f2efa93d4781f4a9410163d 100644 (file)
@@ -35,7 +35,7 @@
                     <div class="col s12">
                         <h5>{{ 'howto.top_menu.bookmarklet'|trans }}</h5>
                         {{ 'howto.bookmarklet.description'|trans }}
-                        {% include 'WallabagCoreBundle::_bookmarklet.html.twig' %}
+                        {% include '@WallabagCore/themes/common/Static/_bookmarklet.html.twig' %}
                     </div>
 
                 </div>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/common/Static/quickstart.html.twig
new file mode 100644 (file)
index 0000000..226bafe
--- /dev/null
@@ -0,0 +1,119 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'quickstart.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel settings">
+
+                <div class="row">
+                    <h3>{{ 'quickstart.intro.title'|trans }}</h3>
+
+                    <ul class="row data">
+                        <li class="col l4 m6 s12">
+                            <div class="card teal darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.configure.title'|trans }}</span>
+                                    <p>{{ 'quickstart.configure.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="{{ path('config') }}">{{ 'quickstart.configure.language'|trans }}</a></li>
+                                        <li><a href="{{ path('config') }}#set2">{{ 'quickstart.configure.rss'|trans }}</a></li>
+                                        <li><a href="{{ path('config') }}#set5">{{ 'quickstart.more'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                        <li class="col l4 m6 s12">
+                            <div class="card green darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.first_steps.title'|trans }}</span>
+                                    <p>{{ 'quickstart.first_steps.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="{{ path('new') }}">{{ 'quickstart.first_steps.new_article'|trans }}</a></li>
+                                        <li><a href="{{ path('unread') }}">{{ 'quickstart.first_steps.unread_articles'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                        <li class="col l4 m6 s12">
+                            <div class="card light-green darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.migrate.title'|trans }}</span>
+                                    <p>{{ 'quickstart.migrate.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="{{ path('import_pocket') }}">{{ 'quickstart.migrate.pocket'|trans }}</a></li>
+                                        <li><a href="{{ path('import_readability') }}">{{ 'quickstart.migrate.readability'|trans }}</a></li>
+                                        <li><a href="{{ path('import_instapaper') }}">{{ 'quickstart.migrate.instapaper'|trans }}</a></li>
+                                        <li><a href="{{ path('import') }}">{{ 'quickstart.more'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                        <li class="col l4 m6 s12">
+                            <div class="card blue darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.developer.title'|trans }}</span>
+                                    <p>{{ 'quickstart.developer.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="{{ path('developer') }}">{{ 'quickstart.developer.create_application'|trans }}</a></li>
+                                        <li><a href="http://doc.wallabag.org/en/master/developer/docker.html">{{ 'quickstart.developer.use_docker'|trans }}</a></li>
+                                        <li><a href="http://doc.wallabag.org/en/master/index.html#dev-docs">{{ 'quickstart.more'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                        <li class="col l4 m6 s12">
+                            <div class="card light-blue darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.docs.title'|trans }}</span>
+                                    <p>{{ 'quickstart.docs.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="http://doc.wallabag.org/en/master/user/annotations.html">{{ 'quickstart.docs.annotate'|trans }}</a></li>
+                                        <li><a href="http://doc.wallabag.org/en/master/user/download_articles.html">{{ 'quickstart.docs.export'|trans }}</a></li>
+                                        <li><a href="http://doc.wallabag.org/">{{ 'quickstart.docs.all_docs'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                        <li class="col l4 m6 s12">
+                            <div class="card cyan darken-1">
+                                <div class="card-content white-text">
+                                    <span class="card-title">{{ 'quickstart.support.title'|trans }}</span>
+                                    <p>{{ 'quickstart.support.description'|trans }}</p>
+                                </div>
+                                <div class="card-action">
+                                    <ul>
+                                        <li><a href="https://github.com/wallabag/wallabag/issues/">{{ 'quickstart.support.github'|trans }}</a></li>
+                                        <li><a href="mailto:hello@wallabag.org">{{ 'quickstart.support.email'|trans }}</a></li>
+                                        <li><a href="https://gitter.im/wallabag/wallabag">{{ 'quickstart.support.gitter'|trans }}</a></li>
+                                    </ul>
+                                </div>
+                            </div>
+                        </li>
+
+                    </ul>
+
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+{% endblock %}
index 5330c35392d92f3dc7c442141e09e88b95201fcf..270c077f332de577644e574849c7ff7acd7e748e 100644 (file)
@@ -16,9 +16,6 @@
                             <li class="tab col s3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li>
                             <li class="tab col s3"><a href="#set4">{{ 'config.tab_menu.password'|trans }}</a></li>
                             <li class="tab col s3"><a href="#set5">{{ 'config.tab_menu.rules'|trans }}</a></li>
-                            {% if is_granted('ROLE_SUPER_ADMIN') %}
-                            <li class="tab col s3"><a href="#set6">{{ 'config.tab_menu.new_user'|trans }}</a></li>
-                            {% endif %}
                         </ul>
                     </div>
 
                             <div class="row">
                                 <div class="input-field col s12">
                                     {{ 'config.form_user.two_factor_description'|trans }}
-                                </div>
-                            </div>
 
-                            <div class="row">
-                                <div class="input-field col s12">
+                                    <br />
+
                                     {{ form_widget(form.user.twoFactorAuthentication) }}
                                     {{ form_label(form.user.twoFactorAuthentication) }}
                                     {{ form_errors(form.user.twoFactorAuthentication) }}
                                         « {{ tagging_rule.rule }} »
                                         {{ 'config.form_rules.then_tag_as_label'|trans }}
                                         « {{ tagging_rule.tags|join(', ') }} »
+                                        <a href="{{ path('edit_tagging_rule', {id: tagging_rule.id}) }}" title="{{ 'config.form_rules.edit_rule_label'|trans }}">
+                                            <i class="tool grey-text mode_edit material-icons">mode_edit</i>
+                                        </a>
                                         <a href="{{ path('delete_tagging_rule', {id: tagging_rule.id}) }}" title="{{ 'config.form_rules.delete_rule_label'|trans }}">
                                             <i class="tool grey-text delete material-icons">delete</i>
                                         </a>
                             </div>
                         </div>
                     </div>
-
-                    {% if is_granted('ROLE_SUPER_ADMIN') %}
-                    <div id="set6" class="col s12">
-                        {{ form_start(form.new_user) }}
-                            {{ form_errors(form.new_user) }}
-
-                            <div class="row">
-                                <div class="input-field col s12">
-                                    {{ form_label(form.new_user.username) }}
-                                    {{ form_errors(form.new_user.username) }}
-                                    {{ form_widget(form.new_user.username) }}
-                                </div>
-                            </div>
-
-                            <div class="row">
-                                <div class="input-field col s12">
-                                    {{ form_label(form.new_user.plainPassword.first) }}
-                                    {{ form_errors(form.new_user.plainPassword.first) }}
-                                    {{ form_widget(form.new_user.plainPassword.first) }}
-                                </div>
-                            </div>
-
-                            <div class="row">
-                                <div class="input-field col s12">
-                                    {{ form_label(form.new_user.plainPassword.second) }}
-                                    {{ form_errors(form.new_user.plainPassword.second) }}
-                                    {{ form_widget(form.new_user.plainPassword.second) }}
-                                </div>
-                            </div>
-
-                            <div class="row">
-                                <div class="input-field col s12">
-                                    {{ form_label(form.new_user.email) }}
-                                    {{ form_errors(form.new_user.email) }}
-                                    {{ form_widget(form.new_user.email) }}
-                                </div>
-                            </div>
-
-                            {{ form_widget(form.new_user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
-                            {{ form_rest(form.new_user) }}
-                        </form>
-                    </div>
-                    {% endif %}
                 </div>
 
             </div>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client.html.twig
deleted file mode 100644 (file)
index 8a5da71..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'developer.client.page_title'|trans }}{% endblock %}
-
-{% block content %}
-<div class="row">
-    <div class="col s12">
-        <div class="card-panel settings">
-
-            <div class="row">
-                <p>{{ 'developer.client.page_description'|trans }}</p>
-                {{ form_start(form) }}
-                {{ form_errors(form) }}
-
-                <div class="input-field col s12">
-                    {{ form_label(form.name) }}
-                    {{ form_errors(form.name) }}
-                    {{ form_widget(form.name) }}
-                </div>
-
-                <div class="input-field col s12">
-                    {{ form_label(form.redirect_uris) }}
-                    {{ form_errors(form.redirect_uris) }}
-                    {{ form_widget(form.redirect_uris) }}
-                </div>
-
-                <a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.client.action_back'|trans }}</a>
-                {{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
-
-                {{ form_rest(form) }}
-            </div>
-
-        </div>
-    </div>
-</div>
-
-{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client_parameters.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/client_parameters.html.twig
deleted file mode 100644 (file)
index b498cce..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'developer.client_parameter.page_title'|trans }}{% endblock %}
-
-{% block content %}
-<div class="row">
-    <div class="col s12">
-        <div class="card-panel settings">
-            <div class="row">
-                <p>{{ 'developer.client_parameter.page_description'|trans }}</p>
-                <ul>
-                    <li>{{ 'developer.client_parameter.field_name'|trans }}: <strong><pre>{{ client_name }}</pre></strong></li>
-                    <li>{{ 'developer.client_parameter.field_id'|trans }}: <strong><pre>{{ client_id }}</pre></strong></li>
-                    <li>{{ 'developer.client_parameter.field_secret'|trans }}: <strong><pre>{{ client_secret }}</pre></strong></li>
-                </ul>
-
-                <a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.client_parameter.back'|trans }}</a>
-                <a href="{{ path('developer_howto_firstapp') }}" class="btn waves-effect waves-light">{{ 'developer.client_parameter.read_howto'|trans }}</a>
-            </div>
-        </div>
-    </div>
-</div>
-{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/howto_app.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/howto_app.html.twig
deleted file mode 100644 (file)
index acbc2c8..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'developer.howto.page_title'|trans }}{% endblock %}
-
-{% block css %}
-    {{ parent() }}
-    <link rel="stylesheet" href="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/themes/prism-dark.min.css') }}">
-{% endblock %}
-
-{% block content %}
-<div class="row">
-    <div class="col s12">
-        <div class="card-panel settings">
-
-            <div class="row">
-                <p>{{ 'developer.howto.description.paragraph_1'|trans|raw }}</p>
-                <p>{{ 'developer.howto.description.paragraph_2'|trans }}</p>
-                <p>{{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}</p>
-                <p>{{ 'developer.howto.description.paragraph_4'|trans }}</p>
-                <p>
-                    <pre><code class="language-bash">http POST http://v2.wallabag.org/oauth/v2/token \
-    grant_type=password \
-    client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \
-    client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \
-    username=yourUsername \
-    password=yourPassw0rd</code></pre>
-                </p>
-                <p>{{ 'developer.howto.description.paragraph_5'|trans }}</p>
-                <p>
-                    <pre><code class="language-bash">HTTP/1.1 200 OK
-Cache-Control: no-store, private
-Connection: close
-Content-Type: application/json
-Date: Tue, 06 Oct 2015 18:24:03 GMT
-Host: localhost:8000
-Pragma: no-cache
-X-Debug-Token: be00a1
-X-Debug-Token-Link: /profiler/be00a1
-X-Powered-By: PHP/5.5.9-1ubuntu4.13
-{
-    "access_token": "ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw",
-    "expires_in": 3600,
-    "refresh_token": "ODBjODU1NWUwNmUzZTBkNDQ5YWVlZTVlMjQ2Y2I0OWM2NTM1ZGM2M2Y3MDhjMTViM2U2MzYxYzRkMDk5ODRlZg",
-    "scope": null,
-    "token_type": "bearer"
-}</code></pre>
-                </p>
-                <p>{{ 'developer.howto.description.paragraph_6'|trans }}</p>
-                <p>
-                    <pre><code class="language-bash">http GET http://v2.wallabag.org/api/entries.json \
-    "Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"</code></pre>
-                </p>
-                <p>{{ 'developer.howto.description.paragraph_7'|trans }}</p>
-                <p>{{ 'developer.howto.description.paragraph_8'|trans({'%link%': path('nelmio_api_doc_index')})|raw }}</p>
-                <p><a href="{{ path('developer') }}" class="waves-effect waves-light grey btn">{{ 'developer.howto.back'|trans }}</a></p>
-            </div>
-
-        </div>
-    </div>
-</div>
-<script src="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/prism.min.js') }}"></script>
-<script src="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/components/prism-bash.min.js') }}"></script>
-{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Developer/index.html.twig
deleted file mode 100644 (file)
index 3430c0d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'developer.page_title'|trans }}{% endblock %}
-
-{% block content %}
-<div class="row">
-    <div class="col s12">
-        <div class="card-panel settings">
-
-            <div class="row">
-                <h3>{{ 'developer.welcome_message'|trans }}</h3>
-
-                <h4>{{ 'developer.documentation'|trans }}</h4>
-
-                <ul>
-                    <li><a href="{{ path('developer_howto_firstapp') }}">{{ 'developer.how_to_first_app'|trans }}</a></li>
-                    <li><a href="http://doc.wallabag.org/en/master/developer/api.html">{{ 'developer.full_documentation'|trans }}</a></li>
-                    <li><a href="{{ path('nelmio_api_doc_index') }}">{{ 'developer.list_methods'|trans }}</a></li>
-                </ul>
-
-                <h4>{{ 'developer.clients.title'|trans }}</h4>
-                <ul>
-                    <li><a href="{{ path('developer_create_client') }}">{{ 'developer.clients.create_new'|trans }}</a></li>
-                </ul>
-
-                <h4>{{ 'developer.existing_clients.title'|trans }}</h4>
-                {% if clients %}
-                    <ul class="collapsible" data-collapsible="expandable">
-                        {% for client in clients %}
-                            <li>
-                                <div class="collapsible-header">{{ client.name }} - #{{ client.id }}</div>
-                                <div class="collapsible-body">
-                                    <table class="striped">
-                                        <tr>
-                                            <td>{{ 'developer.existing_clients.field_id'|trans }}</td>
-                                            <td><strong><code>{{ client.id }}_{{ client.randomId }}</code></strong></td>
-                                        </tr>
-                                        <tr>
-                                            <td>{{ 'developer.existing_clients.field_secret'|trans }}</td>
-                                            <td><strong><code>{{ client.secret }}</code></strong></td>
-                                        </tr>
-                                        <tr>
-                                            <td>{{ 'developer.existing_clients.field_uris'|trans }}</td>
-                                            <td><strong><code>{{ client.redirectUris|json_encode() }}</code></strong></td>
-                                        </tr>
-                                        <tr>
-                                            <td>{{ 'developer.existing_clients.field_grant_types'|trans }}</td>
-                                            <td><strong><code>{{ client.allowedGrantTypes|json_encode() }}</code></strong></td>
-                                        </tr>
-                                    </table>
-                                    <p>
-                                        {{ 'developer.remove.warn_message_1'|trans({'%name%': client.name }) }}<br/>
-                                        {{ 'developer.remove.warn_message_2'|trans({'%name%': client.name }) }}<br/>
-                                        <a class="waves-effect waves-light red btn" href="{{ path('developer_delete_client', {'id': client.id}) }}">{{ 'developer.remove.action'|trans({'%name%': client.name }) }}</a>
-                                    </p>
-                                </div>
-                            </li>
-                        {% endfor %}
-                    </ul>
-                {% else %}
-                    {{ 'developer.existing_clients.no_client'|trans }}
-                {% endif %}
-            </div>
-
-        </div>
-    </div>
-</div>
-
-{% endblock %}
index 1c5057ddd102784366ca99c1f4913b1f23eb31fc..01fde953e2505c812937c9d09e44a0cfa0effad6 100644 (file)
@@ -1,7 +1,7 @@
 {% extends "WallabagCoreBundle::layout.html.twig" %}
 
 {% block title %}
-  {% include "@WallabagCore/themes/_title.html.twig" %}
+  {% include "@WallabagCore/themes/common/Entry/_title.html.twig" %}
 {% endblock %}
 
 {% block content %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.xml.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.xml.twig
deleted file mode 100644 (file)
index 288bb54..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
-    <channel>
-        <title>wallabag — {{type}} feed</title>
-        <link>{{ url('unread') }}</link>
-        <pubDate>{{ "now"|date('D, d M Y H:i:s') }}</pubDate>
-        <generator>wallabag</generator>
-        <description>wallabag {{type}} elements</description>
-
-        {% for entry in entries %}
-
-            <item>
-                <title><![CDATA[{{ entry.title }}]]></title>
-                <source url="{{ url('view', { 'id': entry.id }) }}">wallabag</source>
-                <link>{{ entry.url }}</link>
-                <guid>{{ entry.url }}</guid>
-                <pubDate>{{ entry.createdAt|date('D, d M Y H:i:s') }}</pubDate>
-                <description>
-                    <![CDATA[{%- if entry.readingTime > 0 -%}{{ 'entry.list.reading_time_minutes'|trans({'%readingTime%': entry.readingTime}) }}{%- else -%}{{ 'entry.list.reading_time_less_one_minute'|trans|raw }}{%- endif %}{{ entry.content|raw -}}]]>
-                </description>
-            </item>
-
-        {% endfor %}
-
-    </channel>
-</rss>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Exception/error.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Exception/error.html.twig
new file mode 100644 (file)
index 0000000..6be78ed
--- /dev/null
@@ -0,0 +1,30 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'error.page_title'|trans }}{% endblock %}
+
+{% block body_class %}login{% endblock %}
+
+{% block menu %}{% endblock %}
+{% block messages %}{% endblock %}
+
+{% block content %}
+<main class="valign-wrapper">
+    <div class="valign row">
+        <div class="card sw">
+            <div class="center"><img src="{{ asset('bundles/wallabagcore/themes/_global/img/logo-other_themes.png') }}" alt="wallabag logo" /></div>
+            <div class="card-content">
+                <div class="row">
+                    <h5>{{ status_code }}: {{ status_text }}</h5>
+                    <p>{{ exception.message }}</p>
+                    {# {% for trace in exception.trace %}
+                        <p>{{ trace.class }} - {{ trace.type }} - {{ trace.file }} - {{ trace.line }}</p>
+                    {% endfor %} #}
+                </div>
+            </div>
+        </div>
+    </div>
+</main>
+{% endblock %}
+
+{% block footer %}
+{% endblock %}
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Static/quickstart.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Static/quickstart.html.twig
deleted file mode 100644 (file)
index 8cbf4ab..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-{% extends "WallabagCoreBundle::layout.html.twig" %}
-
-{% block title %}{{ 'quickstart.page_title'|trans }}{% endblock %}
-
-{% block content %}
-
-    <div class="row">
-        <div class="col s12">
-            <div class="card-panel settings">
-
-                <div class="row">
-                    <h3>{{ 'quickstart.intro.title'|trans }}</h3>
-                    <p>{{ 'quickstart.intro.paragraph_1'|trans }}</p>
-                    <p>{{ 'quickstart.intro.paragraph_2'|trans }}</p>
-
-                    <h4>{{ 'quickstart.configure.title'|trans }}</h4>
-                    <ul>
-                        <li><a href="{{ path('config') }}">{{ 'quickstart.configure.language'|trans }}</a></li>
-                        <li><a href="{{ path('config') }}#set2">{{ 'quickstart.configure.rss'|trans }}</a></li>
-                        <li><a href="{{ path('config') }}#set5">{{ 'quickstart.configure.tagging_rules'|trans }}</a></li>
-                    </ul>
-
-                    {% if is_granted('ROLE_SUPER_ADMIN') %}
-                    <h4>{{ 'quickstart.admin.title'|trans }}</h4>
-                    <p>{{ 'quickstart.admin.description'|trans }}</p>
-                    <ul>
-                        <li><a href="{{ path('config') }}#set6">{{ 'quickstart.admin.new_user'|trans }}</a></li>
-                        <li><a href="{{ path('craue_config_settings_modify') }}#set-analytics">{{ 'quickstart.admin.analytics'|trans }}</a></li>
-                        <li><a href="{{ path('craue_config_settings_modify') }}#set-entry">{{ 'quickstart.admin.sharing'|trans }}</a></li>
-                        <li><a href="{{ path('craue_config_settings_modify') }}#set-export">{{ 'quickstart.admin.export'|trans }}</a></li>
-                        <li><a href="{{ path('craue_config_settings_modify') }}#set-import">{{ 'quickstart.admin.import'|trans }}</a></li>
-                    </ul>
-                    {% endif %}
-
-                    <h4>{{ 'quickstart.first_steps.title'|trans }}</h4>
-                    <ul>
-                        <li><a href="{{ path('new') }}">{{ 'quickstart.first_steps.new_article'|trans }}</a></li>
-                        <li><a href="{{ path('unread') }}">{{ 'quickstart.first_steps.unread_articles'|trans }}</a></li>
-                    </ul>
-
-                    <h4>{{ 'quickstart.migrate.title'|trans }}</h4>
-                    <p>{{ 'quickstart.migrate.description'|trans }}</p>
-                    <ul>
-                        <li><a href="{{ path('import_pocket') }}">{{ 'quickstart.migrate.pocket'|trans }}</a></li>
-                        <li><a href="{{ path('import_wallabag_v1') }}">{{ 'quickstart.migrate.wallabag_v1'|trans }}</a></li>
-                        <li><a href="{{ path('import_wallabag_v2') }}">{{ 'quickstart.migrate.wallabag_v2'|trans }}</a></li>
-                        <li><a href="{{ path('import_readability') }}">{{ 'quickstart.migrate.readability'|trans }}</a></li>
-                    </ul>
-
-                    <h4>{{ 'quickstart.developer.title'|trans }}</h4>
-                    <ul>
-                        <li><a href="{{ path('developer') }}">{{ 'quickstart.developer.create_application'|trans }}</a></li>
-                    </ul>
-
-                    <h4>{{ 'quickstart.docs.title'|trans }}</h4>
-                    <ul>
-                        <li><a href="http://doc.wallabag.org/en/master/user/annotations.html">{{ 'quickstart.docs.annotate'|trans }}</a></li>
-                        <li><a href="http://doc.wallabag.org/en/master/user/download_articles.html">{{ 'quickstart.docs.export'|trans }}</a></li>
-                        <li><a href="http://doc.wallabag.org/en/master/user/filters.html">{{ 'quickstart.docs.search_filters'|trans }}</a></li>
-                        <li><a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html">{{ 'quickstart.docs.fetching_errors'|trans }}</a></li>
-                        <li><a href="http://doc.wallabag.org/">{{ 'quickstart.docs.all_docs'|trans }}</a></li>
-                    </ul>
-
-                    <h4>{{ 'quickstart.support.title'|trans }}</h4>
-                    <p>{{ 'quickstart.support.description'|trans }}</p>
-                    <ul>
-                        <li><a href="https://github.com/wallabag/wallabag/issues/">{{ 'quickstart.support.github'|trans }}</a></li>
-                        <li><a href="mailto:hello@wallabag.org">{{ 'quickstart.support.email'|trans }}</a></li>
-                        <li><a href="https://gitter.im/wallabag/wallabag">{{ 'quickstart.support.gitter'|trans }}</a></li>
-                    </ul>
-                </div>
-
-            </div>
-        </div>
-    </div>
-
-{% endblock %}
index df05e2a4890bd5dfd5d4aa751ec5dfbf46436540..c7d6d70d3f03df06b5d945df5a9e0859dc62d442 100644 (file)
@@ -45,7 +45,7 @@
             <li class="bold {% if currentRoute == 'archive' %}active{% endif %}">
                 <a class="waves-effect" href="{{ path('archive') }}">{{ 'menu.left.archive'|trans }} <span class="numberItems grey-text">{{ count_entries('archive') }}</span></a>
             </li>
-            <li class="bold border-bottom {% if currentRoute == 'all' %}active{% endif %}">
+            <li class="bold {% if currentRoute == 'all' %}active{% endif %}">
                 <a class="waves-effect" href="{{ path('all') }}">{{ 'menu.left.all_articles'|trans }} <span class="numberItems grey-text">{{ count_entries('all') }}</span></a>
             </li>
             <li class="bold border-bottom {% if currentRoute == 'tags' %}active{% endif %}">
                 <a class="waves-effect" href="{{ path('config') }}">{{ 'menu.left.config'|trans }}</a>
             </li>
             {% if is_granted('ROLE_SUPER_ADMIN') %}
+                <li class="bold {% if currentRoute starts with 'user_' %}active{% endif %}">
+                    <a class="waves-effect" href="{{ path('user_index') }}">{{ 'menu.left.users_management'|trans }}</a>
+                </li>
+
                 <li class="bold border-bottom {% if currentRoute == 'craue_config_settings_modify' %}active{% endif %}">
                     <a class="waves-effect" href="{{ path('craue_config_settings_modify') }}">{{ 'menu.left.internal_settings'|trans }}</a>
                 </li>
     <footer class="page-footer cyan darken-2">
         <div class="footer-copyright">
             <div class="container">
-                <p>{{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a></p>
-                <a class="grey-text text-lighten-4 right" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans }}</a>
+                <div class="row">
+                    <div class="col s8">
+                        <p>
+                            {{ display_stats() }}
+                        </p>
+                    </div>
+                    <div class="col s4">
+                        <p>
+                            {{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a> –
+                            <a class="grey-text text-lighten-4" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans|lower }}</a>
+                        </p>
+                    </div>
+                </div>
             </div>
         </div>
     </footer>
index fb4c7412395f4affcb3b4b73f844ea06d498d4cc..783cde3e70897aedb877f45f8ad0562a5b68cc9b 100644 (file)
@@ -5,6 +5,7 @@ namespace Wallabag\CoreBundle\Twig;
 use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
 use Wallabag\CoreBundle\Repository\EntryRepository;
 use Wallabag\CoreBundle\Repository\TagRepository;
+use Symfony\Component\Translation\TranslatorInterface;
 
 class WallabagExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface
 {
@@ -12,13 +13,15 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
     private $entryRepository;
     private $tagRepository;
     private $lifeTime;
+    private $translator;
 
-    public function __construct(EntryRepository $entryRepository = null, TagRepository $tagRepository = null, TokenStorageInterface $tokenStorage = null, $lifeTime = 0)
+    public function __construct(EntryRepository $entryRepository, TagRepository $tagRepository, TokenStorageInterface $tokenStorage, $lifeTime, TranslatorInterface $translator)
     {
         $this->entryRepository = $entryRepository;
         $this->tagRepository = $tagRepository;
         $this->tokenStorage = $tokenStorage;
         $this->lifeTime = $lifeTime;
+        $this->translator = $translator;
     }
 
     public function getFilters()
@@ -33,6 +36,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
         return array(
             new \Twig_SimpleFunction('count_entries', [$this, 'countEntries']),
             new \Twig_SimpleFunction('count_tags', [$this, 'countTags']),
+            new \Twig_SimpleFunction('display_stats', [$this, 'displayStats']),
         );
     }
 
@@ -107,6 +111,40 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
         return $this->tagRepository->countAllTags($user->getId());
     }
 
+    /**
+     * Display a single line about reading stats.
+     *
+     * @return string
+     */
+    public function displayStats()
+    {
+        $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
+
+        if (null === $user || !is_object($user)) {
+            return 0;
+        }
+
+        $query = $this->entryRepository->getBuilderForArchiveByUser($user->getId())
+            ->select('e.id')
+            ->groupBy('e.id')
+            ->getQuery();
+
+        $query->useQueryCache(true);
+        $query->useResultCache(true);
+        $query->setResultCacheLifetime($this->lifeTime);
+
+        $nbArchives = count($query->getArrayResult());
+
+        $interval = $user->getCreatedAt()->diff(new \DateTime('now'));
+        $nbDays = (int) $interval->format('%a') ?: 1;
+
+        return $this->translator->trans('footer.stats', [
+            '%user_creation%' => $user->getCreatedAt()->format('F jS, Y'),
+            '%nb_archives%' => $nbArchives,
+            '%per_day%' => round($nbArchives / $nbDays, 2),
+        ]);
+    }
+
     public function getName()
     {
         return 'wallabag_extension';
index 5f90e00fa8b0b5e071f751983cd30befcc4a4dec..c2c11f1181e85c3232819b7698fc040e35964417 100644 (file)
@@ -17,7 +17,7 @@ class RedisWorkerCommand extends ContainerAwareCommand
         $this
             ->setName('wallabag:import:redis-worker')
             ->setDescription('Launch Redis worker')
-            ->addArgument('serviceName', InputArgument::REQUIRED, 'Service to use: wallabag_v1, wallabag_v2, pocket or readability')
+            ->addArgument('serviceName', InputArgument::REQUIRED, 'Service to use: wallabag_v1, wallabag_v2, pocket, readability, firefox, chrome or instapaper')
             ->addOption('maxIterations', '', InputOption::VALUE_OPTIONAL, 'Number of iterations before stoping', false)
         ;
     }
index 36a2a399d12f80bbd10381e1ea799d6ae2d08cc8..15de75ffdc824160c5cda2c4298a0b71194ab35c 100644 (file)
@@ -38,7 +38,11 @@ class ImportController extends Controller
                 $nbRabbitMessages = $this->getTotalMessageInRabbitQueue('pocket')
                     + $this->getTotalMessageInRabbitQueue('readability')
                     + $this->getTotalMessageInRabbitQueue('wallabag_v1')
-                    + $this->getTotalMessageInRabbitQueue('wallabag_v2');
+                    + $this->getTotalMessageInRabbitQueue('wallabag_v2')
+                    + $this->getTotalMessageInRabbitQueue('firefox')
+                    + $this->getTotalMessageInRabbitQueue('chrome')
+                    + $this->getTotalMessageInRabbitQueue('instapaper')
+                ;
             } catch (\Exception $e) {
                 $rabbitNotInstalled = true;
             }
@@ -49,7 +53,11 @@ class ImportController extends Controller
                 $nbRedisMessages = $redis->llen('wallabag.import.pocket')
                     + $redis->llen('wallabag.import.readability')
                     + $redis->llen('wallabag.import.wallabag_v1')
-                    + $redis->llen('wallabag.import.wallabag_v2');
+                    + $redis->llen('wallabag.import.wallabag_v2')
+                    + $redis->llen('wallabag.import.firefox')
+                    + $redis->llen('wallabag.import.chrome')
+                    + $redis->llen('wallabag.import.instapaper')
+                ;
             } catch (\Exception $e) {
                 $redisNotInstalled = true;
             }
diff --git a/src/Wallabag/ImportBundle/Controller/InstapaperController.php b/src/Wallabag/ImportBundle/Controller/InstapaperController.php
new file mode 100644 (file)
index 0000000..c3fc8a3
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wallabag\ImportBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Symfony\Component\HttpFoundation\Request;
+use Wallabag\ImportBundle\Form\Type\UploadImportType;
+
+class InstapaperController extends Controller
+{
+    /**
+     * @Route("/instapaper", name="import_instapaper")
+     */
+    public function indexAction(Request $request)
+    {
+        $form = $this->createForm(UploadImportType::class);
+        $form->handleRequest($request);
+
+        $instapaper = $this->get('wallabag_import.instapaper.import');
+        $instapaper->setUser($this->getUser());
+
+        if ($this->get('craue_config')->get('import_with_rabbitmq')) {
+            $instapaper->setProducer($this->get('old_sound_rabbit_mq.import_instapaper_producer'));
+        } elseif ($this->get('craue_config')->get('import_with_redis')) {
+            $instapaper->setProducer($this->get('wallabag_import.producer.redis.instapaper'));
+        }
+
+        if ($form->isValid()) {
+            $file = $form->get('file')->getData();
+            $markAsRead = $form->get('mark_as_read')->getData();
+            $name = 'instapaper_'.$this->getUser()->getId().'.csv';
+
+            if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes')) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
+                $res = $instapaper
+                    ->setFilepath($this->getParameter('wallabag_import.resource_dir').'/'.$name)
+                    ->setMarkAsRead($markAsRead)
+                    ->import();
+
+                $message = 'flashes.import.notice.failed';
+
+                if (true === $res) {
+                    $summary = $instapaper->getSummary();
+                    $message = $this->get('translator')->trans('flashes.import.notice.summary', [
+                        '%imported%' => $summary['imported'],
+                        '%skipped%' => $summary['skipped'],
+                    ]);
+
+                    if (0 < $summary['queued']) {
+                        $message = $this->get('translator')->trans('flashes.import.notice.summary_with_queue', [
+                            '%queued%' => $summary['queued'],
+                        ]);
+                    }
+
+                    unlink($this->getParameter('wallabag_import.resource_dir').'/'.$name);
+                }
+
+                $this->get('session')->getFlashBag()->add(
+                    'notice',
+                    $message
+                );
+
+                return $this->redirect($this->generateUrl('homepage'));
+            } else {
+                $this->get('session')->getFlashBag()->add(
+                    'notice',
+                    'flashes.import.notice.failed_on_file'
+                );
+            }
+        }
+
+        return $this->render('WallabagImportBundle:Instapaper:index.html.twig', [
+            'form' => $form->createView(),
+            'import' => $instapaper,
+        ]);
+    }
+}
index a1a14576f13213e0869f940ab05ee5ec1bc3f224..764b390a830428fbdc60ddf6a793d8d632fb75b0 100644 (file)
@@ -106,6 +106,10 @@ abstract class AbstractImport implements ImportInterface
         $i = 1;
 
         foreach ($entries as $importedEntry) {
+            if ($this->markAsRead) {
+                $importedEntry = $this->setEntryAsRead($importedEntry);
+            }
+
             $entry = $this->parseEntry($importedEntry);
 
             if (null === $entry) {
index e15443c40a6de26ac485b321658c496d79fda853..9d75685b74d84aa13c9d90d9672b5893f271f2fd 100644 (file)
@@ -45,6 +45,8 @@ abstract class BrowserImport extends AbstractImport
         $data = json_decode(file_get_contents($this->filepath), true);
 
         if (empty($data)) {
+            $this->logger->error('Wallabag Browser: no entries in imported file');
+
             return false;
         }
 
diff --git a/src/Wallabag/ImportBundle/Import/InstapaperImport.php b/src/Wallabag/ImportBundle/Import/InstapaperImport.php
new file mode 100644 (file)
index 0000000..cf4c785
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+
+namespace Wallabag\ImportBundle\Import;
+
+use Wallabag\CoreBundle\Entity\Entry;
+
+class InstapaperImport extends AbstractImport
+{
+    private $filepath;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'Instapaper';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getUrl()
+    {
+        return 'import_instapaper';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getDescription()
+    {
+        return 'import.instapaper.description';
+    }
+
+    /**
+     * Set file path to the json file.
+     *
+     * @param string $filepath
+     */
+    public function setFilepath($filepath)
+    {
+        $this->filepath = $filepath;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function import()
+    {
+        if (!$this->user) {
+            $this->logger->error('InstapaperImport: user is not defined');
+
+            return false;
+        }
+
+        if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
+            $this->logger->error('InstapaperImport: unable to read file', ['filepath' => $this->filepath]);
+
+            return false;
+        }
+
+        $entries = [];
+        $handle = fopen($this->filepath, 'r');
+        while (($data = fgetcsv($handle, 10240)) !== false) {
+            if ('URL' === $data[0]) {
+                continue;
+            }
+
+            $entries[] = [
+                'url' => $data[0],
+                'title' => $data[1],
+                'status' => $data[3],
+                'is_archived' => $data[3] === 'Archive' || $data[3] === 'Starred',
+                'is_starred' => $data[3] === 'Starred',
+                'content_type' => '',
+                'language' => '',
+            ];
+        }
+        fclose($handle);
+
+        if (empty($entries)) {
+            $this->logger->error('InstapaperImport: no entries in imported file');
+
+            return false;
+        }
+
+        if ($this->producer) {
+            $this->parseEntriesForProducer($entries);
+
+            return true;
+        }
+
+        $this->parseEntries($entries);
+
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function parseEntry(array $importedEntry)
+    {
+        $existingEntry = $this->em
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findByUrlAndUserId($importedEntry['url'], $this->user->getId());
+
+        if (false !== $existingEntry) {
+            ++$this->skippedEntries;
+
+            return;
+        }
+
+        $entry = new Entry($this->user);
+        $entry->setUrl($importedEntry['url']);
+        $entry->setTitle($importedEntry['title']);
+
+        // update entry with content (in case fetching failed, the given entry will be return)
+        $entry = $this->fetchContent($entry, $importedEntry['url'], $importedEntry);
+
+        $entry->setArchived($importedEntry['is_archived']);
+        $entry->setStarred($importedEntry['is_starred']);
+
+        $this->em->persist($entry);
+        ++$this->importedEntries;
+
+        return $entry;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function setEntryAsRead(array $importedEntry)
+    {
+        $importedEntry['is_archived'] = 1;
+
+        return $importedEntry;
+    }
+}
index fa2b705391707848389189a5810c2937303b5498..b8c0f777094e8d33a3645d528560df0d19812183 100644 (file)
@@ -64,6 +64,8 @@ class ReadabilityImport extends AbstractImport
         $data = json_decode(file_get_contents($this->filepath), true);
 
         if (empty($data) || empty($data['bookmarks'])) {
+            $this->logger->error('ReadabilityImport: no entries in imported file');
+
             return false;
         }
 
index 3754e4a95ce54e5799e72248f90a4b54d95509ae..702da057a0b996b0e8b305f84b86db07c642eb81 100644 (file)
@@ -58,6 +58,8 @@ abstract class WallabagImport extends AbstractImport
         $data = json_decode(file_get_contents($this->filepath), true);
 
         if (empty($data)) {
+            $this->logger->error('WallabagImport: no entries in imported file');
+
             return false;
         }
 
index 6ada630251028c5f0ad30a89840303d6022c8b11..70b8a0d47cc744113a17e3d450f92bb01482c575 100644 (file)
@@ -14,6 +14,13 @@ services:
             - "@wallabag_user.user_repository"
             - "@wallabag_import.readability.import"
             - "@logger"
+    wallabag_import.consumer.amqp.instapaper:
+        class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
+        arguments:
+            - "@doctrine.orm.entity_manager"
+            - "@wallabag_user.user_repository"
+            - "@wallabag_import.instapaper.import"
+            - "@logger"
     wallabag_import.consumer.amqp.wallabag_v1:
         class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
         arguments:
index c9c2cf26e1f76e2f887b6b0e9301ec82e9e757b2..0a81e1b556c0584c5aa490424e72b7f057c01e89 100644 (file)
@@ -20,6 +20,26 @@ services:
             - "@wallabag_import.readability.import"
             - "@logger"
 
+    # instapaper
+    wallabag_import.queue.redis.instapaper:
+        class: Simpleue\Queue\RedisQueue
+        arguments:
+            - "@wallabag_core.redis.client"
+            - "wallabag.import.instapaper"
+
+    wallabag_import.producer.redis.instapaper:
+        class: Wallabag\ImportBundle\Redis\Producer
+        arguments:
+            - "@wallabag_import.queue.redis.instapaper"
+
+    wallabag_import.consumer.redis.instapaper:
+        class: Wallabag\ImportBundle\Consumer\RedisEntryConsumer
+        arguments:
+            - "@doctrine.orm.entity_manager"
+            - "@wallabag_user.user_repository"
+            - "@wallabag_import.instapaper.import"
+            - "@logger"
+
     # pocket
     wallabag_import.queue.redis.pocket:
         class: Simpleue\Queue\RedisQueue
index 990f336dfd5338ffc983bd06fdc1632d27f149f3..89adc71b3453a4dd720b3a99bcc0ce5a438a1fd1 100644 (file)
@@ -57,6 +57,16 @@ services:
         tags:
             -  { name: wallabag_import.import, alias: readability }
 
+    wallabag_import.instapaper.import:
+        class: Wallabag\ImportBundle\Import\InstapaperImport
+        arguments:
+            - "@doctrine.orm.entity_manager"
+            - "@wallabag_core.content_proxy"
+        calls:
+            - [ setLogger, [ "@logger" ]]
+        tags:
+            -  { name: wallabag_import.import, alias: instapaper }
+
     wallabag_import.firefox.import:
         class: Wallabag\ImportBundle\Import\FirefoxImport
         arguments:
diff --git a/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig b/src/Wallabag/ImportBundle/Resources/views/Instapaper/index.html.twig
new file mode 100644 (file)
index 0000000..5789361
--- /dev/null
@@ -0,0 +1,45 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'import.instapaper.page_title'|trans }}{% endblock %}
+
+{% block content %}
+<div class="row">
+    <div class="col s12">
+        <div class="card-panel settings">
+            {% include 'WallabagImportBundle:Import:_workerEnabled.html.twig' %}
+
+            <div class="row">
+                <blockquote>{{ import.description|trans }}</blockquote>
+                <p>{{ 'import.instapaper.how_to'|trans }}</p>
+
+                <div class="col s12">
+                    {{ form_start(form, {'method': 'POST'}) }}
+                        {{ form_errors(form) }}
+                        <div class="row">
+                            <div class="file-field input-field col s12">
+                                {{ form_errors(form.file) }}
+                                <div class="btn">
+                                    <span>{{ form.file.vars.label|trans }}</span>
+                                    {{ form_widget(form.file) }}
+                                </div>
+                                <div class="file-path-wrapper">
+                                    <input class="file-path validate" type="text">
+                                </div>
+                            </div>
+                            <div class="input-field col s6 with-checkbox">
+                                <h6>{{ 'import.form.mark_as_read_title'|trans }}</h6>
+                                {{ form_widget(form.mark_as_read) }}
+                                {{ form_label(form.mark_as_read) }}
+                            </div>
+                        </div>
+
+                        {{ form_widget(form.save, { 'attr': {'class': 'btn waves-effect waves-light'} }) }}
+
+                        {{ form_rest(form) }}
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+{% endblock %}
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php
new file mode 100644 (file)
index 0000000..92ee2b4
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+
+namespace Wallabag\UserBundle\Controller;
+
+use FOS\UserBundle\Event\UserEvent;
+use FOS\UserBundle\FOSUserEvents;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Wallabag\UserBundle\Entity\User;
+use Wallabag\CoreBundle\Entity\Config;
+
+/**
+ * User controller.
+ */
+class ManageController extends Controller
+{
+    /**
+     * Lists all User entities.
+     *
+     * @Route("/", name="user_index")
+     * @Method("GET")
+     */
+    public function indexAction()
+    {
+        $em = $this->getDoctrine()->getManager();
+
+        $users = $em->getRepository('WallabagUserBundle:User')->findAll();
+
+        return $this->render('WallabagUserBundle:Manage:index.html.twig', array(
+            'users' => $users,
+        ));
+    }
+
+    /**
+     * Creates a new User entity.
+     *
+     * @Route("/new", name="user_new")
+     * @Method({"GET", "POST"})
+     */
+    public function newAction(Request $request)
+    {
+        $userManager = $this->container->get('fos_user.user_manager');
+
+        $user = $userManager->createUser();
+        // enable created user by default
+        $user->setEnabled(true);
+
+        $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [
+            'validation_groups' => ['Profile'],
+        ]);
+        $form->handleRequest($request);
+
+        if ($form->isSubmitted() && $form->isValid()) {
+            $userManager->updateUser($user);
+
+            // dispatch a created event so the associated config will be created
+            $event = new UserEvent($user, $request);
+            $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event);
+
+            $this->get('session')->getFlashBag()->add(
+                'notice',
+                $this->get('translator')->trans('flashes.user.notice.added', ['%username%' => $user->getUsername()])
+            );
+
+            return $this->redirectToRoute('user_edit', array('id' => $user->getId()));
+        }
+
+        return $this->render('WallabagUserBundle:Manage:new.html.twig', array(
+            'user' => $user,
+            'form' => $form->createView(),
+        ));
+    }
+
+    /**
+     * Displays a form to edit an existing User entity.
+     *
+     * @Route("/{id}/edit", name="user_edit")
+     * @Method({"GET", "POST"})
+     */
+    public function editAction(Request $request, User $user)
+    {
+        $deleteForm = $this->createDeleteForm($user);
+        $editForm = $this->createForm('Wallabag\UserBundle\Form\UserType', $user);
+        $editForm->handleRequest($request);
+
+        if ($editForm->isSubmitted() && $editForm->isValid()) {
+            $em = $this->getDoctrine()->getManager();
+            $em->persist($user);
+            $em->flush();
+
+            $this->get('session')->getFlashBag()->add(
+                'notice',
+                $this->get('translator')->trans('flashes.user.notice.updated', ['%username%' => $user->getUsername()])
+            );
+
+            return $this->redirectToRoute('user_edit', array('id' => $user->getId()));
+        }
+
+        return $this->render('WallabagUserBundle:Manage:edit.html.twig', array(
+            'user' => $user,
+            'edit_form' => $editForm->createView(),
+            'delete_form' => $deleteForm->createView(),
+            'twofactor_auth' => $this->getParameter('twofactor_auth'),
+        ));
+    }
+
+    /**
+     * Deletes a User entity.
+     *
+     * @Route("/{id}", name="user_delete")
+     * @Method("DELETE")
+     */
+    public function deleteAction(Request $request, User $user)
+    {
+        $form = $this->createDeleteForm($user);
+        $form->handleRequest($request);
+
+        if ($form->isSubmitted() && $form->isValid()) {
+            $this->get('session')->getFlashBag()->add(
+                'notice',
+                $this->get('translator')->trans('flashes.user.notice.deleted', ['%username%' => $user->getUsername()])
+            );
+
+            $em = $this->getDoctrine()->getManager();
+            $em->remove($user);
+            $em->flush();
+        }
+
+        return $this->redirectToRoute('user_index');
+    }
+
+    /**
+     * Creates a form to delete a User entity.
+     *
+     * @param User $user The User entity
+     *
+     * @return \Symfony\Component\Form\Form The form
+     */
+    private function createDeleteForm(User $user)
+    {
+        return $this->createFormBuilder()
+            ->setAction($this->generateUrl('user_delete', array('id' => $user->getId())))
+            ->setMethod('DELETE')
+            ->getForm()
+        ;
+    }
+}
index dfed8e47d4ab52000319f3536205004c7f87365b..d98ae76a533d5871f0befb514b13fbaab4ec9a98 100644 (file)
@@ -64,7 +64,7 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
     protected $entries;
 
     /**
-     * @ORM\OneToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", mappedBy="user")
+     * @ORM\OneToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", mappedBy="user", cascade={"remove"})
      */
     protected $config;
 
similarity index 53%
rename from src/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListener.php
rename to src/Wallabag/UserBundle/EventListener/CreateConfigListener.php
index 10586126fe35f43ef5ae45a1d1e635686259adb0..15f4ac3dee41faad596d6b56484d3cc1858b6e41 100644 (file)
@@ -1,39 +1,49 @@
 <?php
 
-namespace Wallabag\CoreBundle\EventListener;
+namespace Wallabag\UserBundle\EventListener;
 
 use Doctrine\ORM\EntityManager;
-use FOS\UserBundle\Event\FilterUserResponseEvent;
+use FOS\UserBundle\Event\UserEvent;
 use FOS\UserBundle\FOSUserEvents;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Wallabag\CoreBundle\Entity\Config;
 
-class RegistrationConfirmedListener implements EventSubscriberInterface
+/**
+ * This listener will create the associated configuration when a user register.
+ * This configuration will be created right after the registration (no matter if it needs an email validation).
+ */
+class CreateConfigListener implements EventSubscriberInterface
 {
     private $em;
     private $theme;
     private $itemsOnPage;
     private $rssLimit;
     private $language;
+    private $readingSpeed;
 
-    public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language)
+    public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language, $readingSpeed)
     {
         $this->em = $em;
         $this->theme = $theme;
         $this->itemsOnPage = $itemsOnPage;
         $this->rssLimit = $rssLimit;
         $this->language = $language;
+        $this->readingSpeed = $readingSpeed;
     }
 
     public static function getSubscribedEvents()
     {
         return [
-            FOSUserEvents::REGISTRATION_CONFIRMED => 'authenticate',
+            // when a user register using the normal form
+            FOSUserEvents::REGISTRATION_COMPLETED => 'createConfig',
+            // when we manually create a user using the command line
+            // OR when we create it from the config UI
+            FOSUserEvents::USER_CREATED => 'createConfig',
         ];
     }
 
-    public function authenticate(FilterUserResponseEvent $event, $eventName = null, EventDispatcherInterface $eventDispatcher = null)
+    public function createConfig(UserEvent $event, $eventName = null, EventDispatcherInterface $eventDispatcher = null)
     {
         if (!$event->getUser()->isEnabled()) {
             return;
@@ -44,6 +54,8 @@ class RegistrationConfirmedListener implements EventSubscriberInterface
         $config->setItemsPerPage($this->itemsOnPage);
         $config->setRssLimit($this->rssLimit);
         $config->setLanguage($this->language);
+        $config->setReadingSpeed($this->readingSpeed);
+
         $this->em->persist($config);
         $this->em->flush();
     }
similarity index 77%
rename from src/Wallabag/CoreBundle/Form/Type/NewUserType.php
rename to src/Wallabag/UserBundle/Form/NewUserType.php
index 6a6f63d166428a990d978f65d7ff4a94f0c9171e..ad5a2405924ae8b6211f9ac4c6928e7f7d31e385 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-namespace Wallabag\CoreBundle\Form\Type;
+namespace Wallabag\UserBundle\Form;
 
 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\Extension\Core\Type\EmailType;
@@ -19,13 +19,13 @@ class NewUserType extends AbstractType
         $builder
             ->add('username', TextType::class, [
                 'required' => true,
-                'label' => 'config.form_new_user.username_label',
+                'label' => 'user.form.username_label',
             ])
             ->add('plainPassword', RepeatedType::class, [
                 'type' => PasswordType::class,
                 'invalid_message' => 'validator.password_must_match',
-                'first_options' => ['label' => 'config.form_new_user.password_label'],
-                'second_options' => ['label' => 'config.form_new_user.repeat_new_password_label'],
+                'first_options' => ['label' => 'user.form.password_label'],
+                'second_options' => ['label' => 'user.form.repeat_new_password_label'],
                 'constraints' => [
                     new Constraints\Length([
                         'min' => 8,
@@ -33,13 +33,13 @@ class NewUserType extends AbstractType
                     ]),
                     new Constraints\NotBlank(),
                 ],
-                'label' => 'config.form_new_user.plain_password_label',
+                'label' => 'user.form.plain_password_label',
             ])
             ->add('email', EmailType::class, [
-                'label' => 'config.form_new_user.email_label',
+                'label' => 'user.form.email_label',
             ])
             ->add('save', SubmitType::class, [
-                'label' => 'config.form.save',
+                'label' => 'user.form.save',
             ])
         ;
     }
diff --git a/src/Wallabag/UserBundle/Form/UserType.php b/src/Wallabag/UserBundle/Form/UserType.php
new file mode 100644 (file)
index 0000000..cfa6779
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+
+namespace Wallabag\UserBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
+use Symfony\Component\Form\Extension\Core\Type\EmailType;
+
+class UserType extends AbstractType
+{
+    /**
+     * @param FormBuilderInterface $builder
+     * @param array                $options
+     */
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add('name', TextType::class, [
+                'required' => false,
+                'label' => 'user.form.name_label',
+            ])
+            ->add('username', TextType::class, [
+                'required' => true,
+                'label' => 'user.form.username_label',
+            ])
+            ->add('email', EmailType::class, [
+                'required' => true,
+                'label' => 'user.form.email_label',
+            ])
+            ->add('enabled', CheckboxType::class, [
+                'required' => false,
+                'label' => 'user.form.enabled_label',
+            ])
+            ->add('locked', CheckboxType::class, [
+                'required' => false,
+                'label' => 'user.form.locked_label',
+            ])
+            ->add('twoFactorAuthentication', CheckboxType::class, [
+                'required' => false,
+                'label' => 'user.form.twofactor_label',
+            ])
+            ->add('save', SubmitType::class, [
+                'label' => 'user.form.save',
+            ])
+        ;
+    }
+
+    /**
+     * @param OptionsResolver $resolver
+     */
+    public function configureOptions(OptionsResolver $resolver)
+    {
+        $resolver->setDefaults(array(
+            'data_class' => 'Wallabag\UserBundle\Entity\User',
+        ));
+    }
+}
index 05830555ee8cb9eee5818598930e3c14fe8ccba4..eb9c8e676e0cbd03b4f92eda2b502a1f5c88ad32 100644 (file)
@@ -20,3 +20,15 @@ services:
         factory: [ "@doctrine.orm.default_entity_manager", getRepository ]
         arguments:
             - WallabagUserBundle:User
+
+    wallabag_user.create_config:
+        class: Wallabag\UserBundle\EventListener\CreateConfigListener
+        arguments:
+            - "@doctrine.orm.entity_manager"
+            - "%wallabag_core.theme%"
+            - "%wallabag_core.items_on_page%"
+            - "%wallabag_core.rss_limit%"
+            - "%wallabag_core.language%"
+            - "%wallabag_core.reading_speed%"
+        tags:
+            - { name: kernel.event_subscriber }
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig
new file mode 100644 (file)
index 0000000..d5cf99c
--- /dev/null
@@ -0,0 +1,86 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'user.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel">
+                <div class="row">
+                    <div class="input-field col s12">
+                        <h4>{{ 'user.edit_user'|trans }}</h4>
+
+                        <div id="set6" class="col s12">
+                            {{ form_start(edit_form) }}
+                                {{ form_errors(edit_form) }}
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(edit_form.name) }}
+                                        {{ form_errors(edit_form.name) }}
+                                        {{ form_widget(edit_form.name) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(edit_form.username) }}
+                                        {{ form_errors(edit_form.username) }}
+                                        {{ form_widget(edit_form.username) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(edit_form.email) }}
+                                        {{ form_errors(edit_form.email) }}
+                                        {{ form_widget(edit_form.email) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_widget(edit_form.enabled) }}
+                                        {{ form_label(edit_form.enabled) }}
+                                        {{ form_errors(edit_form.enabled) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_widget(edit_form.locked) }}
+                                        {{ form_label(edit_form.locked) }}
+                                        {{ form_errors(edit_form.locked) }}
+                                    </div>
+                                </div>
+
+                                {% if twofactor_auth %}
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_widget(edit_form.twoFactorAuthentication) }}
+                                        {{ form_label(edit_form.twoFactorAuthentication) }}
+                                        {{ form_errors(edit_form.twoFactorAuthentication) }}
+                                    </div>
+                                </div>
+                                {% endif %}
+
+                                <br/>
+
+                                {{ form_widget(edit_form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
+                                {{ form_rest(edit_form) }}
+                            </form>
+                            <p>
+                                {{ form_start(delete_form) }}
+                                    <button {% if app.user.id == user.id %}disabled="disabled"{% endif %} onclick="return confirm('{{ 'user.form.delete_confirm'|trans|escape('js') }}')" type="submit" class="btn waves-effect waves-light red">{{ 'user.form.delete'|trans }}</button>
+                                {{ form_end(delete_form) }}
+                            </p>
+                            <p><a class="waves-effect waves-light btn blue-grey" href="{{ path('user_index') }}">{{ 'user.form.back_to_list'|trans }}</a></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+{% endblock %}
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig
new file mode 100644 (file)
index 0000000..996bdb1
--- /dev/null
@@ -0,0 +1,48 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'user.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel">
+                <div class="row">
+                    <div class="input-field col s12">
+                        <p class="help">{{ 'user.description'|trans|raw }}</p>
+
+                        <table class="bordered">
+                            <thead>
+                                <tr>
+                                    <th>{{ 'user.form.username_label'|trans }}</th>
+                                    <th>{{ 'user.form.email_label'|trans }}</th>
+                                    <th>{{ 'user.form.last_login_label'|trans }}</th>
+                                    <th>{{ 'user.form.locked_label'|trans }}</th>
+                                    <th>{{ 'user.list.actions'|trans }}</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                            {% for user in users %}
+                                <tr>
+                                    <td>{{ user.username }}</td>
+                                    <td>{{ user.email }}</td>
+                                    <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td>
+                                    <td>{% if user.locked %}{{ 'user.list.yes'|trans }}{% else %}{{ 'user.list.no'|trans }}{% endif %}</td>
+                                    <td>
+                                        <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a>
+                                    </td>
+                                </tr>
+                            {% endfor %}
+                            </tbody>
+                        </table>
+                        <br />
+                        <p>
+                            <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a>
+                        </p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+{% endblock %}
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig
new file mode 100644 (file)
index 0000000..8c894c0
--- /dev/null
@@ -0,0 +1,61 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'user.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel">
+                <div class="row">
+                    <div class="input-field col s12">
+                        <h4>{{ 'user.new_user'|trans }}</h4>
+
+                        <div id="set6" class="col s12">
+                            {{ form_start(form) }}
+                                {{ form_errors(form) }}
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(form.username) }}
+                                        {{ form_errors(form.username) }}
+                                        {{ form_widget(form.username) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(form.plainPassword.first) }}
+                                        {{ form_errors(form.plainPassword.first) }}
+                                        {{ form_widget(form.plainPassword.first) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(form.plainPassword.second) }}
+                                        {{ form_errors(form.plainPassword.second) }}
+                                        {{ form_widget(form.plainPassword.second) }}
+                                    </div>
+                                </div>
+
+                                <div class="row">
+                                    <div class="input-field col s12">
+                                        {{ form_label(form.email) }}
+                                        {{ form_errors(form.email) }}
+                                        {{ form_widget(form.email) }}
+                                    </div>
+                                </div>
+
+                                {{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
+                                {{ form_rest(form) }}
+                            </form>
+                            <p><a class="waves-effect waves-light btn blue-grey" href="{{ path('user_index') }}">{{ 'user.form.back_to_list'|trans }}</a></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+{% endblock %}
diff --git a/src/Wallabag/UserBundle/Resources/views/manage.html.twig b/src/Wallabag/UserBundle/Resources/views/manage.html.twig
new file mode 100644 (file)
index 0000000..c614c55
--- /dev/null
@@ -0,0 +1,43 @@
+{% extends "WallabagCoreBundle::layout.html.twig" %}
+
+{% block title %}{{ 'user.manage.page_title'|trans }}{% endblock %}
+
+{% block content %}
+
+    <div class="row">
+        <div class="col s12">
+            <div class="card-panel">
+                <div class="row">
+                    <div class="input-field col s12">
+                        <p class="help">{{ 'user.manage.description'|trans|raw }}</p>
+
+                        <table class="bordered">
+                            <thead>
+                                <tr>
+                                    <th>{{ 'user.manage.field.username'|trans }}</th>
+                                    <th>{{ 'user.manage.field.email'|trans }}</th>
+                                    <th>{{ 'user.manage.field.last_login'|trans }}</th>
+                                    <th>{{ 'user.manage.field.locked'|trans }}</th>
+                                    <th>{{ 'user.manage.action'|trans }}</th>
+                                </tr>
+                            </thead>
+
+                            <tbody>
+                                {% for user in users %}
+                                    <tr>
+                                        <td>{{ user.username }}</td>
+                                        <td>{{ user.email }}</td>
+                                        <td>{{ user.lastLogin|date('d/m/Y H:i:s') }}</td>
+                                        <td>{{ user.locked ? 'yes' : 'no' }}</td>
+                                        <td>edit - delete</td>
+                                    </tr>
+                                {% endfor %}
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+{% endblock %}
index 101c20eb69fd82572d85f0549f633e41e4ecd21e..fd72b8f2234a31d9769f947ae32e2722cb460ecb 100644 (file)
@@ -78,6 +78,53 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         );
     }
 
+    public function testGetEntriesWithFullOptions()
+    {
+        $this->client->request('GET', '/api/entries', [
+            'archive' => 1,
+            'starred' => 1,
+            'sort' => 'updated',
+            'order' => 'asc',
+            'page' => 1,
+            'perPage' => 2,
+            'tags' => 'foo',
+            'since' => 1443274283,
+        ]);
+
+        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+        $content = json_decode($this->client->getResponse()->getContent(), true);
+
+        $this->assertGreaterThanOrEqual(1, count($content));
+        $this->assertArrayHasKey('items', $content['_embedded']);
+        $this->assertGreaterThanOrEqual(0, $content['total']);
+        $this->assertEquals(1, $content['page']);
+        $this->assertEquals(2, $content['limit']);
+        $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('archive=1', $content['_links'][$link]['href']);
+            $this->assertContains('starred=1', $content['_links'][$link]['href']);
+            $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+            $this->assertContains('order=asc', $content['_links'][$link]['href']);
+            $this->assertContains('tags=foo', $content['_links'][$link]['href']);
+            $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+        }
+
+        $this->assertTrue(
+            $this->client->getResponse()->headers->contains(
+                'Content-Type',
+                'application/json'
+            )
+        );
+    }
+
     public function testGetStarredEntries()
     {
         $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
@@ -92,6 +139,17 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         $this->assertEquals(1, $content['page']);
         $this->assertGreaterThanOrEqual(1, $content['pages']);
 
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('starred=1', $content['_links'][$link]['href']);
+            $this->assertContains('sort=updated', $content['_links'][$link]['href']);
+        }
+
         $this->assertTrue(
             $this->client->getResponse()->headers->contains(
                 'Content-Type',
@@ -114,6 +172,16 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         $this->assertEquals(1, $content['page']);
         $this->assertGreaterThanOrEqual(1, $content['pages']);
 
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('archive=1', $content['_links'][$link]['href']);
+        }
+
         $this->assertTrue(
             $this->client->getResponse()->headers->contains(
                 'Content-Type',
@@ -136,6 +204,16 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         $this->assertEquals(1, $content['page']);
         $this->assertGreaterThanOrEqual(1, $content['pages']);
 
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']);
+        }
+
         $this->assertTrue(
             $this->client->getResponse()->headers->contains(
                 'Content-Type',
@@ -146,7 +224,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase
 
     public function testGetDatedEntries()
     {
-        $this->client->request('GET', '/api/entries', ['since' => 1]);
+        $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
 
         $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
 
@@ -158,6 +236,16 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         $this->assertEquals(1, $content['page']);
         $this->assertGreaterThanOrEqual(1, $content['pages']);
 
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
+        }
+
         $this->assertTrue(
             $this->client->getResponse()->headers->contains(
                 'Content-Type',
@@ -181,6 +269,16 @@ class WallabagRestControllerTest extends WallabagApiTestCase
         $this->assertEquals(1, $content['page']);
         $this->assertEquals(1, $content['pages']);
 
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
+        }
+
         $this->assertTrue(
             $this->client->getResponse()->headers->contains(
                 'Content-Type',
@@ -684,4 +782,26 @@ class WallabagRestControllerTest extends WallabagApiTestCase
 
         $this->assertEquals(true, $content['is_starred']);
     }
+
+    public function testGetEntriesExists()
+    {
+        $this->client->request('GET', '/api/entries/exists?url=http://0.0.0.0/entry2');
+
+        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+        $content = json_decode($this->client->getResponse()->getContent(), true);
+
+        $this->assertEquals(true, $content['exists']);
+    }
+
+    public function testGetEntriesExistsWhichDoesNotExists()
+    {
+        $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
+
+        $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+        $content = json_decode($this->client->getResponse()->getContent(), true);
+
+        $this->assertEquals(false, $content['exists']);
+    }
 }
index 7193f9b0e4331976f2768557425af73ec36faa2a..1954c654a53fba9f7882d62ad524907fcd6fa069 100644 (file)
@@ -28,7 +28,6 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertCount(1, $crawler->filter('button[id=config_save]'));
         $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]'));
         $this->assertCount(1, $crawler->filter('button[id=update_user_save]'));
-        $this->assertCount(1, $crawler->filter('button[id=new_user_save]'));
         $this->assertCount(1, $crawler->filter('button[id=rss_config_save]'));
     }
 
@@ -56,8 +55,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
 
         $crawler = $client->followRedirect();
 
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.config_saved', $alert[0]);
+        $this->assertContains('flashes.config.notice.config_saved', $crawler->filter('body')->extract(['_text'])[0]);
     }
 
     public function testChangeReadingSpeed()
@@ -213,8 +211,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
 
         $crawler = $client->followRedirect();
 
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.password_updated', $alert[0]);
+        $this->assertContains('flashes.config.notice.password_updated', $crawler->filter('body')->extract(['_text'])[0]);
     }
 
     public function dataForUserFailed()
@@ -285,120 +282,6 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertContains('flashes.config.notice.user_updated', $alert[0]);
     }
 
-    public function dataForNewUserFailed()
-    {
-        return [
-            [
-                [
-                    'new_user[username]' => '',
-                    'new_user[plainPassword][first]' => '',
-                    'new_user[plainPassword][second]' => '',
-                    'new_user[email]' => '',
-                ],
-                'fos_user.username.blank',
-            ],
-            [
-                [
-                    'new_user[username]' => 'a',
-                    'new_user[plainPassword][first]' => 'mypassword',
-                    'new_user[plainPassword][second]' => 'mypassword',
-                    'new_user[email]' => '',
-                ],
-                'fos_user.username.short',
-            ],
-            [
-                [
-                    'new_user[username]' => 'wallace',
-                    'new_user[plainPassword][first]' => 'mypassword',
-                    'new_user[plainPassword][second]' => 'mypassword',
-                    'new_user[email]' => 'test',
-                ],
-                'fos_user.email.invalid',
-            ],
-            [
-                [
-                    'new_user[username]' => 'admin',
-                    'new_user[plainPassword][first]' => 'wallacewallace',
-                    'new_user[plainPassword][second]' => 'wallacewallace',
-                    'new_user[email]' => 'wallace@wallace.me',
-                ],
-                'fos_user.username.already_used',
-            ],
-            [
-                [
-                    'new_user[username]' => 'wallace',
-                    'new_user[plainPassword][first]' => 'mypassword1',
-                    'new_user[plainPassword][second]' => 'mypassword2',
-                    'new_user[email]' => 'wallace@wallace.me',
-                ],
-                'validator.password_must_match',
-            ],
-        ];
-    }
-
-    /**
-     * @dataProvider dataForNewUserFailed
-     */
-    public function testNewUserFailed($data, $expectedMessage)
-    {
-        $this->logInAs('admin');
-        $client = $this->getClient();
-
-        $crawler = $client->request('GET', '/config');
-
-        $this->assertEquals(200, $client->getResponse()->getStatusCode());
-
-        $form = $crawler->filter('button[id=new_user_save]')->form();
-
-        $crawler = $client->submit($form, $data);
-
-        $this->assertEquals(200, $client->getResponse()->getStatusCode());
-
-        $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
-        $this->assertContains($expectedMessage, $alert[0]);
-    }
-
-    public function testNewUserCreated()
-    {
-        $this->logInAs('admin');
-        $client = $this->getClient();
-
-        $crawler = $client->request('GET', '/config');
-
-        $this->assertEquals(200, $client->getResponse()->getStatusCode());
-
-        $form = $crawler->filter('button[id=new_user_save]')->form();
-
-        $data = [
-            'new_user[username]' => 'wallace',
-            'new_user[plainPassword][first]' => 'wallace1',
-            'new_user[plainPassword][second]' => 'wallace1',
-            'new_user[email]' => 'wallace@wallace.me',
-        ];
-
-        $client->submit($form, $data);
-
-        $this->assertEquals(302, $client->getResponse()->getStatusCode());
-
-        $crawler = $client->followRedirect();
-
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.user_added', $alert[0]);
-
-        $em = $client->getContainer()->get('doctrine.orm.entity_manager');
-        $user = $em
-            ->getRepository('WallabagUserBundle:User')
-            ->findOneByUsername('wallace');
-
-        $this->assertTrue(false !== $user);
-        $this->assertTrue($user->isEnabled());
-        $this->assertEquals('material', $user->getConfig()->getTheme());
-        $this->assertEquals(12, $user->getConfig()->getItemsPerPage());
-        $this->assertEquals(50, $user->getConfig()->getRssLimit());
-        $this->assertEquals('en', $user->getConfig()->getLanguage());
-        $this->assertEquals(1, $user->getConfig()->getReadingSpeed());
-    }
-
     public function testRssUpdateResetToken()
     {
         $this->logInAs('admin');
@@ -474,8 +357,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
 
         $crawler = $client->followRedirect();
 
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.rss_updated', $alert[0]);
+        $this->assertContains('flashes.config.notice.rss_updated', $crawler->filter('body')->extract(['_text'])[0]);
     }
 
     public function dataForRssFailed()
@@ -540,8 +422,32 @@ class ConfigControllerTest extends WallabagCoreTestCase
 
         $crawler = $client->followRedirect();
 
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.tagging_rules_updated', $alert[0]);
+        $this->assertContains('flashes.config.notice.tagging_rules_updated', $crawler->filter('body')->extract(['_text'])[0]);
+
+        $editLink = $crawler->filter('.mode_edit')->last()->link();
+
+        $crawler = $client->click($editLink);
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+        $this->assertContains('?tagging-rule=', $client->getResponse()->headers->get('location'));
+
+        $crawler = $client->followRedirect();
+
+        $form = $crawler->filter('button[id=tagging_rule_save]')->form();
+
+        $data = [
+            'tagging_rule[rule]' => 'readingTime <= 30',
+            'tagging_rule[tags]' => 'short reading',
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $this->assertContains('flashes.config.notice.tagging_rules_updated', $crawler->filter('body')->extract(['_text'])[0]);
+
+        $this->assertContains('readingTime <= 30', $crawler->filter('body')->extract(['_text'])[0]);
 
         $deleteLink = $crawler->filter('.delete')->last()->link();
 
@@ -549,8 +455,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
         $this->assertEquals(302, $client->getResponse()->getStatusCode());
 
         $crawler = $client->followRedirect();
-        $this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(['_text']));
-        $this->assertContains('flashes.config.notice.tagging_rules_deleted', $alert[0]);
+        $this->assertContains('flashes.config.notice.tagging_rules_deleted', $crawler->filter('body')->extract(['_text'])[0]);
     }
 
     public function dataForTaggingRuleFailed()
@@ -613,7 +518,23 @@ class ConfigControllerTest extends WallabagCoreTestCase
             ->getRepository('WallabagCoreBundle:TaggingRule')
             ->findAll()[0];
 
-        $crawler = $client->request('GET', '/tagging-rule/delete/'.$rule->getId());
+        $crawler = $client->request('GET', '/tagging-rule/edit/'.$rule->getId());
+
+        $this->assertEquals(403, $client->getResponse()->getStatusCode());
+        $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('You can not access this tagging rule', $body[0]);
+    }
+
+    public function testEditingTaggingRuleFromAnOtherUser()
+    {
+        $this->logInAs('bob');
+        $client = $this->getClient();
+
+        $rule = $client->getContainer()->get('doctrine.orm.entity_manager')
+            ->getRepository('WallabagCoreBundle:TaggingRule')
+            ->findAll()[0];
+
+        $crawler = $client->request('GET', '/tagging-rule/edit/'.$rule->getId());
 
         $this->assertEquals(403, $client->getResponse()->getStatusCode());
         $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
index a74c17d9549372324632edbf5910765c9d6a8087..c40e10a50041135efd2b49af3ba57edba2e8adda 100644 (file)
@@ -29,7 +29,7 @@ class EntryControllerTest extends WallabagCoreTestCase
 
         $this->assertEquals(200, $client->getResponse()->getStatusCode());
         $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
-        $this->assertContains('quickstart.intro.paragraph_1', $body[0]);
+        $this->assertContains('quickstart.intro.title', $body[0]);
 
         // Test if quickstart is disabled when user has 1 entry
         $crawler = $client->request('GET', '/new');
@@ -160,6 +160,50 @@ class EntryControllerTest extends WallabagCoreTestCase
         $this->assertContains('/view/', $client->getResponse()->getTargetUrl());
     }
 
+    public function testPostNewOkUrlExistWithAccent()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $url = 'http://www.aritylabs.com/post/106091708292/des-contr%C3%B4leurs-optionnels-gr%C3%A2ce-%C3%A0-constmissing';
+
+        $crawler = $client->request('GET', '/new');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+        $form = $crawler->filter('form[name=entry]')->form();
+
+        $data = [
+            'entry[url]' => $url,
+        ];
+
+        $client->submit($form, $data);
+
+        $crawler = $client->request('GET', '/new');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+        $form = $crawler->filter('form[name=entry]')->form();
+
+        $data = [
+            'entry[url]' => $url,
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+        $this->assertContains('/view/', $client->getResponse()->getTargetUrl());
+
+        $em = $client->getContainer()
+            ->get('doctrine.orm.entity_manager');
+        $entry = $em
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findOneByUrl(urldecode($url));
+
+        $em->remove($entry);
+        $em->flush();
+    }
+
     /**
      * This test will require an internet connection.
      */
index 71652760d8a592c2729147ff4691527d1c819d3b..2c32393f74449f373c3a0e168c40dc36ca213cdb 100644 (file)
@@ -47,7 +47,7 @@ class TagControllerTest extends WallabagCoreTestCase
 
         $this->assertEquals(1, count($entry->getTags()));
 
-        # tag already exists and already assigned
+        // tag already exists and already assigned
         $client->submit($form, $data);
         $this->assertEquals(302, $client->getResponse()->getStatusCode());
 
@@ -58,7 +58,7 @@ class TagControllerTest extends WallabagCoreTestCase
 
         $this->assertEquals(1, count($newEntry->getTags()));
 
-        # tag already exists but still not assigned to this entry
+        // tag already exists but still not assigned to this entry
         $data = [
             'tag[label]' => 'foo',
         ];
index e29b58b5795c35f3e29d4c56cf854f00f2af541e..2e6fccfb152fe8830efddad032b8b15e9e95bb17 100644 (file)
@@ -125,16 +125,14 @@ class UsernameRssTokenConverterTest extends \PHPUnit_Framework_TestCase
         $this->assertTrue($converter->supports($params));
     }
 
-    /**
-     * @expectedException InvalidArgumentException
-     * @expectedExceptionMessage Route attribute is missing
-     */
     public function testApplyEmptyRequest()
     {
         $params = new ParamConverter([]);
         $converter = new UsernameRssTokenConverter();
 
-        $converter->apply(new Request(), $params);
+        $res = $converter->apply(new Request(), $params);
+
+        $this->assertFalse($res);
     }
 
     /**
index 8ec2a75a228b1c202117525e7353f152dd1b1a50..b1c8c946315f4995918fdfbeca37798b39a572a3 100644 (file)
@@ -8,7 +8,23 @@ class WallabagExtensionTest extends \PHPUnit_Framework_TestCase
 {
     public function testRemoveWww()
     {
-        $extension = new WallabagExtension();
+        $entryRepository = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $tagRepository = $this->getMockBuilder('Wallabag\CoreBundle\Repository\TagRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $extension = new WallabagExtension($entryRepository, $tagRepository, $tokenStorage, 0, $translator);
 
         $this->assertEquals('lemonde.fr', $extension->removeWww('www.lemonde.fr'));
         $this->assertEquals('lemonde.fr', $extension->removeWww('lemonde.fr'));
index 75b7ee0bd4a110437cdd226455eea0dda7634304..4f103921a78cf6c7c56aa36da70cfb48726ec274 100644 (file)
@@ -83,7 +83,7 @@ abstract class WallabagCoreTestCase extends WebTestCase
 
     /**
      * Check if Redis is installed.
-     * If not, mark test as skip
+     * If not, mark test as skip.
      */
     protected function checkRedis()
     {
index b6783a560e71986737c6bcab2170d65ce0951ad8..0bc40bddc6dd85f6f8e30b2fa60126184b636ff4 100644 (file)
@@ -24,6 +24,6 @@ class ImportControllerTest extends WallabagCoreTestCase
         $crawler = $client->request('GET', '/import/');
 
         $this->assertEquals(200, $client->getResponse()->getStatusCode());
-        $this->assertEquals(6, $crawler->filter('blockquote')->count());
+        $this->assertEquals(7, $crawler->filter('blockquote')->count());
     }
 }
diff --git a/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php b/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
new file mode 100644 (file)
index 0000000..9df08e7
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+
+namespace Tests\Wallabag\ImportBundle\Controller;
+
+use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+
+class InstapaperControllerTest extends WallabagCoreTestCase
+{
+    public function testImportInstapaper()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/import/instapaper');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+        $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
+        $this->assertEquals(1, $crawler->filter('input[type=file]')->count());
+    }
+
+    public function testImportInstapaperWithRabbitEnabled()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 1);
+
+        $crawler = $client->request('GET', '/import/instapaper');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+        $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
+        $this->assertEquals(1, $crawler->filter('input[type=file]')->count());
+
+        $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
+    }
+
+    public function testImportInstapaperBadFile()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/import/instapaper');
+        $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+        $data = [
+            'upload_import_file[file]' => '',
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+    }
+
+    public function testImportInstapaperWithRedisEnabled()
+    {
+        $this->checkRedis();
+        $this->logInAs('admin');
+        $client = $this->getClient();
+        $client->getContainer()->get('craue_config')->set('import_with_redis', 1);
+
+        $crawler = $client->request('GET', '/import/instapaper');
+
+        $this->assertEquals(200, $client->getResponse()->getStatusCode());
+        $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
+        $this->assertEquals(1, $crawler->filter('input[type=file]')->count());
+
+        $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+        $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper.csv');
+
+        $data = [
+            'upload_import_file[file]' => $file,
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('flashes.import.notice.summary', $body[0]);
+
+        $this->assertNotEmpty($client->getContainer()->get('wallabag_core.redis.client')->lpop('wallabag.import.instapaper'));
+
+        $client->getContainer()->get('craue_config')->set('import_with_redis', 0);
+    }
+
+    public function testImportInstapaperWithFile()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/import/instapaper');
+        $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+        $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper.csv');
+
+        $data = [
+            'upload_import_file[file]' => $file,
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $content = $client->getContainer()
+            ->get('doctrine.orm.entity_manager')
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findByUrlAndUserId(
+                'http://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551',
+                $this->getLoggedInUserId()
+            );
+
+        $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('flashes.import.notice.summary', $body[0]);
+
+        $this->assertNotEmpty($content->getMimetype());
+        $this->assertNotEmpty($content->getPreviewPicture());
+        $this->assertNotEmpty($content->getLanguage());
+        $this->assertEquals(0, count($content->getTags()));
+        $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
+    }
+
+    public function testImportInstapaperWithFileAndMarkAllAsRead()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/import/instapaper');
+        $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+        $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper-read.csv');
+
+        $data = [
+            'upload_import_file[file]' => $file,
+            'upload_import_file[mark_as_read]' => 1,
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $content1 = $client->getContainer()
+            ->get('doctrine.orm.entity_manager')
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findByUrlAndUserId(
+                'https://redditblog.com/2016/09/20/amp-and-reactredux/',
+                $this->getLoggedInUserId()
+            );
+
+        $this->assertTrue($content1->isArchived());
+
+        $content2 = $client->getContainer()
+            ->get('doctrine.orm.entity_manager')
+            ->getRepository('WallabagCoreBundle:Entry')
+            ->findByUrlAndUserId(
+                'https://medium.com/@the_minh/why-foursquare-swarm-is-still-my-favourite-social-network-e38228493e6c',
+                $this->getLoggedInUserId()
+            );
+
+        $this->assertTrue($content2->isArchived());
+
+        $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('flashes.import.notice.summary', $body[0]);
+    }
+
+    public function testImportInstapaperWithEmptyFile()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/import/instapaper');
+        $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
+
+        $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt');
+
+        $data = [
+            'upload_import_file[file]' => $file,
+        ];
+
+        $client->submit($form, $data);
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+        $crawler = $client->followRedirect();
+
+        $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+        $this->assertContains('flashes.import.notice.failed', $body[0]);
+    }
+}
diff --git a/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php b/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php
new file mode 100644 (file)
index 0000000..75900bd
--- /dev/null
@@ -0,0 +1,233 @@
+<?php
+
+namespace Tests\Wallabag\ImportBundle\Import;
+
+use Wallabag\ImportBundle\Import\InstapaperImport;
+use Wallabag\UserBundle\Entity\User;
+use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\ImportBundle\Redis\Producer;
+use Monolog\Logger;
+use Monolog\Handler\TestHandler;
+use Simpleue\Queue\RedisQueue;
+use M6Web\Component\RedisMock\RedisMockFactory;
+
+class InstapaperImportTest extends \PHPUnit_Framework_TestCase
+{
+    protected $user;
+    protected $em;
+    protected $logHandler;
+    protected $contentProxy;
+
+    private function getInstapaperImport($unsetUser = false)
+    {
+        $this->user = new User();
+
+        $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $import = new InstapaperImport($this->em, $this->contentProxy);
+
+        $this->logHandler = new TestHandler();
+        $logger = new Logger('test', [$this->logHandler]);
+        $import->setLogger($logger);
+
+        if (false === $unsetUser) {
+            $import->setUser($this->user);
+        }
+
+        return $import;
+    }
+
+    public function testInit()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+
+        $this->assertEquals('Instapaper', $instapaperImport->getName());
+        $this->assertNotEmpty($instapaperImport->getUrl());
+        $this->assertEquals('import.instapaper.description', $instapaperImport->getDescription());
+    }
+
+    public function testImport()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv');
+
+        $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $entryRepo->expects($this->exactly(3))
+            ->method('findByUrlAndUserId')
+            ->willReturn(false);
+
+        $this->em
+            ->expects($this->any())
+            ->method('getRepository')
+            ->willReturn($entryRepo);
+
+        $entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->contentProxy
+            ->expects($this->exactly(3))
+            ->method('updateEntry')
+            ->willReturn($entry);
+
+        $res = $instapaperImport->import();
+
+        $this->assertTrue($res);
+        $this->assertEquals(['skipped' => 0, 'imported' => 3, 'queued' => 0], $instapaperImport->getSummary());
+    }
+
+    public function testImportAndMarkAllAsRead()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv');
+
+        $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $entryRepo->expects($this->exactly(3))
+            ->method('findByUrlAndUserId')
+            ->will($this->onConsecutiveCalls(false, true, true));
+
+        $this->em
+            ->expects($this->any())
+            ->method('getRepository')
+            ->willReturn($entryRepo);
+
+        $this->contentProxy
+            ->expects($this->once())
+            ->method('updateEntry')
+            ->willReturn(new Entry($this->user));
+
+        // check that every entry persisted are archived
+        $this->em
+            ->expects($this->once())
+            ->method('persist')
+            ->with($this->callback(function ($persistedEntry) {
+                return $persistedEntry->isArchived();
+            }));
+
+        $res = $instapaperImport->setMarkAsRead(true)->import();
+
+        $this->assertTrue($res);
+
+        $this->assertEquals(['skipped' => 2, 'imported' => 1, 'queued' => 0], $instapaperImport->getSummary());
+    }
+
+    public function testImportWithRabbit()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv');
+
+        $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $entryRepo->expects($this->never())
+            ->method('findByUrlAndUserId');
+
+        $this->em
+            ->expects($this->never())
+            ->method('getRepository');
+
+        $entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->contentProxy
+            ->expects($this->never())
+            ->method('updateEntry');
+
+        $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $producer
+            ->expects($this->exactly(3))
+            ->method('publish');
+
+        $instapaperImport->setProducer($producer);
+
+        $res = $instapaperImport->setMarkAsRead(true)->import();
+
+        $this->assertTrue($res);
+        $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 3], $instapaperImport->getSummary());
+    }
+
+    public function testImportWithRedis()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv');
+
+        $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $entryRepo->expects($this->never())
+            ->method('findByUrlAndUserId');
+
+        $this->em
+            ->expects($this->never())
+            ->method('getRepository');
+
+        $entry = $this->getMockBuilder('Wallabag\CoreBundle\Entity\Entry')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->contentProxy
+            ->expects($this->never())
+            ->method('updateEntry');
+
+        $factory = new RedisMockFactory();
+        $redisMock = $factory->getAdapter('Predis\Client', true);
+
+        $queue = new RedisQueue($redisMock, 'instapaper');
+        $producer = new Producer($queue);
+
+        $instapaperImport->setProducer($producer);
+
+        $res = $instapaperImport->setMarkAsRead(true)->import();
+
+        $this->assertTrue($res);
+        $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 3], $instapaperImport->getSummary());
+
+        $this->assertNotEmpty($redisMock->lpop('instapaper'));
+    }
+
+    public function testImportBadFile()
+    {
+        $instapaperImport = $this->getInstapaperImport();
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx');
+
+        $res = $instapaperImport->import();
+
+        $this->assertFalse($res);
+
+        $records = $this->logHandler->getRecords();
+        $this->assertContains('InstapaperImport: unable to read file', $records[0]['message']);
+        $this->assertEquals('ERROR', $records[0]['level_name']);
+    }
+
+    public function testImportUserNotDefined()
+    {
+        $instapaperImport = $this->getInstapaperImport(true);
+        $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv');
+
+        $res = $instapaperImport->import();
+
+        $this->assertFalse($res);
+
+        $records = $this->logHandler->getRecords();
+        $this->assertContains('InstapaperImport: user is not defined', $records[0]['message']);
+        $this->assertEquals('ERROR', $records[0]['level_name']);
+    }
+}
diff --git a/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv b/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv
new file mode 100644 (file)
index 0000000..28a4c8e
--- /dev/null
@@ -0,0 +1,4 @@
+URL,Title,Selection,Folder
+http://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551,Baumettes : un tour en cellule,,Unread
+https://redditblog.com/2016/09/20/amp-and-reactredux/,AMP and React+Redux: Why Not?,,Archive
+https://medium.com/@the_minh/why-foursquare-swarm-is-still-my-favourite-social-network-e38228493e6c,Why Foursquare / Swarm is still my favourite social network,,Starred
diff --git a/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php b/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php
new file mode 100644 (file)
index 0000000..19b824b
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+
+namespace Wallabag\UserBundle\Tests\Controller;
+
+use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
+
+class ManageControllerTest extends WallabagCoreTestCase
+{
+    public function testLogin()
+    {
+        $client = $this->getClient();
+
+        $client->request('GET', '/users/');
+
+        $this->assertEquals(302, $client->getResponse()->getStatusCode());
+        $this->assertContains('login', $client->getResponse()->headers->get('location'));
+    }
+
+    public function testCompleteScenario()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        // Create a new user in the database
+        $crawler = $client->request('GET', '/users/');
+        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /users/");
+        $crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link());
+
+        // Fill in the form and submit it
+        $form = $crawler->selectButton('user.form.save')->form(array(
+            'new_user[username]' => 'test_user',
+            'new_user[email]' => 'test@test.io',
+            'new_user[plainPassword][first]' => 'test',
+            'new_user[plainPassword][second]' => 'test',
+        ));
+
+        $client->submit($form);
+        $client->followRedirect();
+        $crawler = $client->request('GET', '/users/');
+
+        // Check data in the show view
+        $this->assertGreaterThan(0, $crawler->filter('td:contains("test_user")')->count(), 'Missing element td:contains("test_user")');
+
+        // Edit the user
+        $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
+
+        $form = $crawler->selectButton('user.form.save')->form(array(
+            'user[name]' => 'Foo User',
+            'user[username]' => 'test_user',
+            'user[email]' => 'test@test.io',
+            'user[enabled]' => true,
+            'user[locked]' => false,
+        ));
+
+        $client->submit($form);
+        $crawler = $client->followRedirect();
+
+        // Check the element contains an attribute with value equals "Foo User"
+        $this->assertGreaterThan(0, $crawler->filter('[value="Foo User"]')->count(), 'Missing element [value="Foo User"]');
+
+        $crawler = $client->request('GET', '/users/');
+        $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
+
+        // Delete the user
+        $client->submit($crawler->selectButton('user.form.delete')->form());
+        $crawler = $client->followRedirect();
+
+        // Check the user has been delete on the list
+        $this->assertNotRegExp('/Foo User/', $client->getResponse()->getContent());
+    }
+
+    public function testDeleteDisabledForLoggedUser()
+    {
+        $this->logInAs('admin');
+        $client = $this->getClient();
+
+        $crawler = $client->request('GET', '/users/'.$this->getLoggedInUserId().'/edit');
+        $disabled = $crawler->selectButton('user.form.delete')->extract('disabled');
+
+        $this->assertEquals('disabled', $disabled[0]);
+    }
+}
similarity index 83%
rename from tests/Wallabag/CoreBundle/EventListener/RegistrationConfirmedListenerTest.php
rename to tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php
index e45722fa78565ecf04fc8071fa3229d8d78e76ce..0cebd3e43731a23dba09040ab0b984a9574e75f1 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-namespace Tests\Wallabag\CoreBundle\EventListener;
+namespace Tests\Wallabag\UserBundle\EventListener;
 
 use FOS\UserBundle\Event\FilterUserResponseEvent;
 use FOS\UserBundle\FOSUserEvents;
@@ -8,10 +8,10 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Wallabag\CoreBundle\Entity\Config;
-use Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener;
+use Wallabag\UserBundle\EventListener\CreateConfigListener;
 use Wallabag\UserBundle\Entity\User;
 
-class RegistrationConfirmedListenerTest extends \PHPUnit_Framework_TestCase
+class CreateConfigListenerTest extends \PHPUnit_Framework_TestCase
 {
     private $em;
     private $listener;
@@ -25,12 +25,13 @@ class RegistrationConfirmedListenerTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->listener = new RegistrationConfirmedListener(
+        $this->listener = new CreateConfigListener(
             $this->em,
             'baggy',
             20,
             50,
-            'fr'
+            'fr',
+            1
         );
 
         $this->dispatcher = new EventDispatcher();
@@ -55,7 +56,7 @@ class RegistrationConfirmedListenerTest extends \PHPUnit_Framework_TestCase
         $this->em->expects($this->never())->method('flush');
 
         $this->dispatcher->dispatch(
-            FOSUserEvents::REGISTRATION_CONFIRMED,
+            FOSUserEvents::REGISTRATION_COMPLETED,
             $event
         );
     }
@@ -76,6 +77,7 @@ class RegistrationConfirmedListenerTest extends \PHPUnit_Framework_TestCase
         $config->setItemsPerPage(20);
         $config->setRssLimit(50);
         $config->setLanguage('fr');
+        $config->setReadingSpeed(1);
 
         $this->em->expects($this->once())
             ->method('persist')
@@ -84,7 +86,7 @@ class RegistrationConfirmedListenerTest extends \PHPUnit_Framework_TestCase
             ->method('flush');
 
         $this->dispatcher->dispatch(
-            FOSUserEvents::REGISTRATION_CONFIRMED,
+            FOSUserEvents::REGISTRATION_COMPLETED,
             $event
         );
     }
index f670c92582d7b0931dc6e890f17d415211f9183b..441d6519f5723537239b9e24f11863418e2abcba 100644 (file)
@@ -37,7 +37,7 @@ class AuthCodeMailerTest extends \PHPUnit_Framework_TestCase
         );
         $this->mailer = new \Swift_Mailer($transport);
 
-        $twigTemplate = <<<TWIG
+        $twigTemplate = <<<'TWIG'
 {% block subject %}subject{% endblock %}
 {% block body_html %}html body {{ code }}{% endblock %}
 {% block body_text %}text body {{ support_url }}{% endblock %}