From 930226b2c588be81891d0170c1a4b62042ac53b0 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 5 Mar 2015 21:41:58 +0100 Subject: Bug fix: 'sqlalchemy.exc.DataError: (DataError) LIMIT must not be negative' when loading the page /articles/id --- pyaggr3g470r/views/article.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyaggr3g470r/views/article.py b/pyaggr3g470r/views/article.py index 66cc0f37..a209f888 100644 --- a/pyaggr3g470r/views/article.py +++ b/pyaggr3g470r/views/article.py @@ -18,10 +18,9 @@ def articles(feed_id=None, nb_articles=-1): feed.articles = controllers.ArticleController(g.user.id)\ .read(feed_id=feed.id)\ .order_by(desc("Article.date")) - if len(feed.articles.all()) <= nb_articles: - nb_articles = -1 - if nb_articles == -1: - feed.articles = feed.articles.limit(nb_articles) + if len(feed.articles.all()) <= nb_articles or nb_articles == -1: + nb_articles = int(1e9) + feed.articles = feed.articles.limit(nb_articles) return render_template('articles.html', feed=feed, nb_articles=nb_articles) -- cgit From 99b2de7b51a77ef883a8ab0e2bfdb2cb8d19ce25 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 5 Mar 2015 21:48:01 +0100 Subject: Capure logging for InsecureRequestWarning (https). --- pyaggr3g470r/lib/crawler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyaggr3g470r/lib/crawler.py b/pyaggr3g470r/lib/crawler.py index 64ef8b6d..68a7efd0 100644 --- a/pyaggr3g470r/lib/crawler.py +++ b/pyaggr3g470r/lib/crawler.py @@ -26,6 +26,7 @@ from requests_futures.sessions import FuturesSession from pyaggr3g470r.lib.utils import default_handler logger = logging.getLogger(__name__) +logging.captureWarnings(True) API_ROOT = "api/v2.0/" -- cgit From c8c3b06168127b5c61f74c0e37300ebbe05f0224 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Fri, 6 Mar 2015 08:53:47 +0100 Subject: Feed GET HTTP resource accepts request with no json data (test). --- pyaggr3g470r/views/api/common.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index 48a0d0ac..bfdc7860 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -1,7 +1,7 @@ """For a given resources, classes in the module intend to create the following routes : GET resource/ - -> to retreive one + -> to retrieve one POST resource -> to create one PUT resource/ @@ -10,7 +10,7 @@ routes : -> to delete one GET resources - -> to retreive several + -> to retrieve several POST resources -> to create several PUT resources @@ -146,12 +146,16 @@ class PyAggResourceExisting(PyAggAbstractResource): class PyAggResourceMulti(PyAggAbstractResource): def get(self): - """retreive several objects. filters can be set in the payload on the + """retrieve several objects. filters can be set in the payload on the different fields of the object, and a limit can be set in there as well """ if 'application/json' != request.headers.get('Content-Type'): raise BadRequest("Content-Type must be application/json") - limit = request.json.pop('limit', 10) + limit = 10 + try: + limit = request.json.pop('limit', 10) + except: + return [res for res in self.controller.read().limit(limit)] if not limit: return [res for res in self.controller.read(**request.json).all()] return [res for res in self.controller.read(**request.json).limit(limit)] -- cgit From 111f15b176433968b5663d7b9138d4b967fa3549 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Fri, 6 Mar 2015 14:37:42 +0100 Subject: Simplified manager.py. --- manager.py | 75 ++++++----------------------------------- pyaggr3g470r/models/__init__.py | 68 ++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 66 deletions(-) diff --git a/manager.py b/manager.py index 348ed9c3..020a0f4c 100755 --- a/manager.py +++ b/manager.py @@ -1,20 +1,10 @@ -#!/usr/bin/env python -import os +#! /usr/bin/env python +# -*- coding: utf-8 -*- + from bootstrap import application, db, populate_g from flask.ext.script import Manager from flask.ext.migrate import Migrate, MigrateCommand -from werkzeug import generate_password_hash - -from sqlalchemy.engine import reflection -from sqlalchemy.schema import ( - MetaData, - Table, - DropTable, - ForeignKeyConstraint, - DropConstraint) - - Migrate(application, db) manager = Manager(application) @@ -23,62 +13,18 @@ manager.add_command('db', MigrateCommand) @manager.command def db_empty(): "Will drop every datas stocked in db." - # From http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DropEverything - conn = db.engine.connect() - - # the transaction only applies if the DB supports - # transactional DDL, i.e. Postgresql, MS SQL Server - trans = conn.begin() - - inspector = reflection.Inspector.from_engine(db.engine) - - # gather all data first before dropping anything. - # some DBs lock after things have been dropped in - # a transaction. - metadata = MetaData() - - tbs = [] - all_fks = [] - - for table_name in inspector.get_table_names(): - fks = [] - for fk in inspector.get_foreign_keys(table_name): - if not fk['name']: - continue - fks.append(ForeignKeyConstraint((), (), name=fk['name'])) - t = Table(table_name, metadata, *fks) - tbs.append(t) - all_fks.extend(fks) - - for fkc in all_fks: - conn.execute(DropConstraint(fkc)) - - for table in tbs: - conn.execute(DropTable(table)) - - trans.commit() + with application.app_context(): + populate_g() + import pyaggr3g470r.models + pyaggr3g470r.models.db_empty(db) @manager.command def db_create(): "Will create the database from conf parameters." with application.app_context(): populate_g() - from pyaggr3g470r.models import User, Role - db.create_all() - - role_admin = Role(name="admin") - role_user = Role(name="user") - - user1 = User(nickname="admin", - email=os.environ.get("ADMIN_EMAIL", - "root@pyAggr3g470r.localhost"), - pwdhash=generate_password_hash( - os.environ.get("ADMIN_PASSWORD", "password")), - activation_key="") - user1.roles.extend([role_admin, role_user]) - - db.session.add(user1) - db.session.commit() + import pyaggr3g470r.models + pyaggr3g470r.models.db_create(db) @manager.command def fetch(user, password, limit=100): @@ -114,6 +60,5 @@ def fetch_asyncio(user_id, feed_id): print("Fetching articles for " + user.nickname) feed_getter = crawler.retrieve_feed(user, feed_id) - if __name__ == '__main__': - manager.run() + manager.run() \ No newline at end of file diff --git a/pyaggr3g470r/models/__init__.py b/pyaggr3g470r/models/__init__.py index 9584d1f2..42903f4e 100644 --- a/pyaggr3g470r/models/__init__.py +++ b/pyaggr3g470r/models/__init__.py @@ -31,5 +31,71 @@ from .role import Role from .user import User from .article import Article - __all__ = ['Feed', 'Role', 'User', 'Article'] + +import os + +from werkzeug import generate_password_hash + +from sqlalchemy.engine import reflection +from sqlalchemy.schema import ( + MetaData, + Table, + DropTable, + ForeignKeyConstraint, + DropConstraint) + +def db_empty(db): + "Will drop every datas stocked in db." + # From http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DropEverything + conn = db.engine.connect() + + # the transaction only applies if the DB supports + # transactional DDL, i.e. Postgresql, MS SQL Server + trans = conn.begin() + + inspector = reflection.Inspector.from_engine(db.engine) + + # gather all data first before dropping anything. + # some DBs lock after things have been dropped in + # a transaction. + metadata = MetaData() + + tbs = [] + all_fks = [] + + for table_name in inspector.get_table_names(): + fks = [] + for fk in inspector.get_foreign_keys(table_name): + if not fk['name']: + continue + fks.append(ForeignKeyConstraint((), (), name=fk['name'])) + t = Table(table_name, metadata, *fks) + tbs.append(t) + all_fks.extend(fks) + + for fkc in all_fks: + conn.execute(DropConstraint(fkc)) + + for table in tbs: + conn.execute(DropTable(table)) + + trans.commit() + +def db_create(db): + "Will create the database from conf parameters." + db.create_all() + + role_admin = Role(name="admin") + role_user = Role(name="user") + + user1 = User(nickname="admin", + email=os.environ.get("ADMIN_EMAIL", + "root@pyAggr3g470r.localhost"), + pwdhash=generate_password_hash( + os.environ.get("ADMIN_PASSWORD", "password")), + activation_key="") + user1.roles.extend([role_admin, role_user]) + + db.session.add(user1) + db.session.commit() \ No newline at end of file -- cgit From c7720beccddf20343027d350bf7b8e4353c82fb5 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Fri, 6 Mar 2015 14:53:31 +0100 Subject: updated documentation (db migration section). --- documentation/migrations.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/migrations.rst b/documentation/migrations.rst index 69f6c974..97d2c0f9 100644 --- a/documentation/migrations.rst +++ b/documentation/migrations.rst @@ -14,11 +14,11 @@ Local migrations .. code-block:: bash - $ python manage.py db upgrade + $ python manager.py db upgrade Remote migrations ----------------- .. code-block:: bash - $ heroku run python manage.py db upgrade + $ heroku run python manager.py db upgrade -- cgit From cc7cbac144891994f30c55b9bbea8a3465f9f091 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 00:20:56 +0100 Subject: Better handling of the error logging in the crawler. --- pyaggr3g470r/crawler.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pyaggr3g470r/crawler.py b/pyaggr3g470r/crawler.py index ebcb8ce4..ded9df6f 100644 --- a/pyaggr3g470r/crawler.py +++ b/pyaggr3g470r/crawler.py @@ -56,7 +56,7 @@ def get(*args, **kwargs): return (yield from response.read_and_close(decode=False)) except Exception as e: #print(e) - return None + raise e @asyncio.coroutine def parse_feed(user, feed): @@ -66,14 +66,17 @@ def parse_feed(user, feed): data = None with (yield from sem): - data = yield from get(feed.link) - - if data is None: - feed.error_count += 1 - if feed.error_count > 2: - feed.enabled = False - db.session.commit() - return + try: + data = yield from get(feed.link) + except Exception as e: + feed.last_error = str(e) + finally: + if data is None: + feed.error_count += 1 + if feed.error_count > 2: + feed.enabled = False + db.session.commit() + return a_feed = feedparser.parse(data) if a_feed['bozo'] == 1: @@ -88,6 +91,7 @@ def parse_feed(user, feed): feed.last_retrieved = datetime.now(dateutil.tz.tzlocal()) feed.error_count = 0 + feed.last_error = "" # Feed informations if feed.title == "": -- cgit From 4e9d887d678db99f26bea677328d59f632522db0 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 11:41:56 +0100 Subject: Updated requirements.txt --- requirements.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3469aef9..8dc23d8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,14 @@ aiohttp -feedparser -opml requests +requests-futures +feedparser beautifulsoup4 lxml +opml +psycopg2 SQLAlchemy +alembic +whoosh Flask Flask-SQLAlchemy Flask-Login @@ -14,11 +18,7 @@ Flask-RESTful Flask-Babel Flask-SSLify Flask-Migrate -flask-Script +Flask-Script WTForms python-postmark -whoosh python-dateutil -alembic -requests-futures==0.9.5 -psycopg2 -- cgit From 2378de49ba37116c5bf93054fd6aed65fa44022a Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 12:07:36 +0100 Subject: Moved duplicate() function in utils.py. Some minor cosmethic changes. --- bootstrap.py | 7 +++++-- pyaggr3g470r/duplicate.py | 20 -------------------- pyaggr3g470r/utils.py | 13 +++++++++++++ pyaggr3g470r/views/api/article.py | 3 +++ pyaggr3g470r/views/api/common.py | 5 +++-- pyaggr3g470r/views/api/feed.py | 9 +++------ pyaggr3g470r/views/article.py | 3 +++ pyaggr3g470r/views/feed.py | 3 +++ pyaggr3g470r/views/views.py | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-) delete mode 100644 pyaggr3g470r/duplicate.py diff --git a/bootstrap.py b/bootstrap.py index 5cfd2250..671552b3 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + # required imports and code exection for basic functionning import os @@ -6,7 +9,7 @@ import logging def set_logging(log_path, log_level=logging.INFO, log_format='%(asctime)s %(levelname)s %(message)s'): - logger = logging.getLogger('pyaggr3g470r') + logger = logging.getLogger('pyAggr3g470r') formater = logging.Formatter(log_format) handler = logging.FileHandler(log_path) handler.setFormatter(formater) @@ -17,7 +20,7 @@ from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy # Create Flask application -application = Flask('pyaggr3g470r') +application = Flask('pyAggr3g470r') application.debug = conf.WEBSERVER_DEBUG set_logging(conf.LOG_PATH, log_level=logging.DEBUG if conf.WEBSERVER_DEBUG else logging.INFO) diff --git a/pyaggr3g470r/duplicate.py b/pyaggr3g470r/duplicate.py deleted file mode 100644 index d4c6e31a..00000000 --- a/pyaggr3g470r/duplicate.py +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env python -#-*- coding: utf-8 -*- - -import itertools -from datetime import timedelta - -from pyaggr3g470r import utils - -def compare_documents(feed): - """ - Compare a list of documents by pair. - """ - duplicates = [] - for pair in itertools.combinations(feed.articles, 2): - date1 = pair[0].date - date2 = pair[1].date - if utils.clear_string(pair[0].title) == utils.clear_string(pair[1].title) and \ - (date1 - date2) < timedelta(days = 1): - duplicates.append(pair) - return duplicates \ No newline at end of file diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index 3ed89f55..ba440c78 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -41,12 +41,14 @@ import logging import datetime import operator import urllib +import itertools import subprocess try: from urlparse import urlparse, parse_qs, urlunparse except: from urllib.parse import urlparse, parse_qs, urlunparse from bs4 import BeautifulSoup +from datetime import timedelta from collections import Counter from contextlib import contextmanager @@ -283,6 +285,17 @@ def tag_cloud(tags): (min(1 + count * 7 / max([tag[1] for tag in tags]), 7), word, format(count, ',d'), word)) \ for (word, count) in tags]) +def compare_documents(feed): + """ + Compare a list of documents by pair. + """ + duplicates = [] + for pair in itertools.combinations(feed.articles, 2): + date1, date2 = pair[0].date, pair[1].date + if clear_string(pair[0].title) == clear_string(pair[1].title) and \ + (date1 - date2) < timedelta(days = 1): + duplicates.append(pair) + return duplicates def search_feed(url): """ diff --git a/pyaggr3g470r/views/api/article.py b/pyaggr3g470r/views/api/article.py index 17881412..c3ec2d34 100644 --- a/pyaggr3g470r/views/api/article.py +++ b/pyaggr3g470r/views/api/article.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + from flask import g import dateutil.parser diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index bfdc7860..856b4bb9 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + """For a given resources, classes in the module intend to create the following routes : GET resource/ @@ -54,13 +57,11 @@ def authenticate(func): and user.activation_key == "": g.user = user logged_in = True - if logged_in: return func(*args, **kwargs) raise Unauthorized({'WWWAuthenticate': 'Basic realm="Login Required"'}) return wrapper - def to_response(func): """Will cast results of func as a result, and try to extract a status_code for the Response object""" diff --git a/pyaggr3g470r/views/api/feed.py b/pyaggr3g470r/views/api/feed.py index 0d83ea43..7d0e2862 100644 --- a/pyaggr3g470r/views/api/feed.py +++ b/pyaggr3g470r/views/api/feed.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + from flask import g from pyaggr3g470r.controllers.feed import FeedController, \ @@ -8,7 +11,6 @@ from pyaggr3g470r.views.api.common import PyAggAbstractResource, \ PyAggResourceExisting, \ PyAggResourceMulti - FEED_ATTRS = {'title': {'type': str}, 'description': {'type': str}, 'link': {'type': str}, @@ -20,25 +22,21 @@ FEED_ATTRS = {'title': {'type': str}, 'last_error': {'type': str}, 'error_count': {'type': int, 'default': 0}} - class FeedNewAPI(PyAggResourceNew): controller_cls = FeedController attrs = FEED_ATTRS to_date = ['date', 'last_retrieved'] - class FeedAPI(PyAggResourceExisting): controller_cls = FeedController attrs = FEED_ATTRS to_date = ['date', 'last_retrieved'] - class FeedsAPI(PyAggResourceMulti): controller_cls = FeedController attrs = FEED_ATTRS to_date = ['date', 'last_retrieved'] - class FetchableFeedAPI(PyAggAbstractResource): controller_cls = FeedController to_date = ['date', 'last_retrieved'] @@ -49,7 +47,6 @@ class FetchableFeedAPI(PyAggAbstractResource): return [feed for feed in self.controller.list_fetchable( **self.reqparse_args())] - g.api.add_resource(FeedNewAPI, '/feed', endpoint='feed_new.json') g.api.add_resource(FeedAPI, '/feed/', endpoint='feed.json') g.api.add_resource(FeedsAPI, '/feeds', endpoint='feeds.json') diff --git a/pyaggr3g470r/views/article.py b/pyaggr3g470r/views/article.py index a209f888..08c92686 100644 --- a/pyaggr3g470r/views/article.py +++ b/pyaggr3g470r/views/article.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + from flask import Blueprint, g, render_template, redirect from sqlalchemy import desc diff --git a/pyaggr3g470r/views/feed.py b/pyaggr3g470r/views/feed.py index 2af502a7..2e39ee4b 100644 --- a/pyaggr3g470r/views/feed.py +++ b/pyaggr3g470r/views/feed.py @@ -1,3 +1,6 @@ +#! /usr/bin/env python +# -*- coding: utf-8 - + from datetime import datetime from flask import Blueprint, g, render_template diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 0f1f8765..9d368c42 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -47,7 +47,7 @@ from sqlalchemy.exc import IntegrityError from werkzeug import generate_password_hash import conf -from pyaggr3g470r import utils, notifications, export, duplicate +from pyaggr3g470r import utils, notifications, export from pyaggr3g470r.models import User, Feed, Article, Role from pyaggr3g470r.decorators import feed_access_required from pyaggr3g470r.forms import SignupForm, SigninForm, AddFeedForm, \ @@ -399,7 +399,7 @@ def duplicates(feed_id=None): """ feed = Feed.query.filter(Feed.user_id == g.user.id, Feed.id == feed_id).first() duplicates = [] - duplicates = duplicate.compare_documents(feed) + duplicates = utils.compare_documents(feed) return render_template('duplicates.html', duplicates=duplicates, feed=feed) @app.route('/index_database', methods=['GET']) -- cgit From 9d733d728c93bfa959a7691aa0c166ffefcc9ae4 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 12:22:21 +0100 Subject: fix. --- bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.py b/bootstrap.py index 671552b3..3b76d0ac 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -9,7 +9,7 @@ import logging def set_logging(log_path, log_level=logging.INFO, log_format='%(asctime)s %(levelname)s %(message)s'): - logger = logging.getLogger('pyAggr3g470r') + logger = logging.getLogger('pyaggr3g470r') formater = logging.Formatter(log_format) handler = logging.FileHandler(log_path) handler.setFormatter(formater) @@ -20,7 +20,7 @@ from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy # Create Flask application -application = Flask('pyAggr3g470r') +application = Flask('pyaggr3g470r') application.debug = conf.WEBSERVER_DEBUG set_logging(conf.LOG_PATH, log_level=logging.DEBUG if conf.WEBSERVER_DEBUG else logging.INFO) -- cgit From 552fd9e276c4eda32b812016cb9d0cbdd49cf87a Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 17:34:42 +0100 Subject: Updated french translations. --- messages.pot | 553 ++++++++++---------- .../translations/fr/LC_MESSAGES/messages.mo | Bin 14305 -> 15220 bytes .../translations/fr/LC_MESSAGES/messages.po | 569 +++++++++++---------- 3 files changed, 592 insertions(+), 530 deletions(-) diff --git a/messages.pot b/messages.pot index da07cc28..2db4ff68 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-01-09 22:12+0100\n" +"POT-Creation-Date: 2015-03-08 17:28+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,308 +17,124 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" -#: pyaggr3g470r/forms.py:39 pyaggr3g470r/forms.py:99 +#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:97 #: pyaggr3g470r/templates/admin/dashboard.html:12 msgid "Nickname" msgstr "" -#: pyaggr3g470r/forms.py:39 pyaggr3g470r/forms.py:99 +#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:98 msgid "Please enter your nickname." msgstr "" -#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:100 pyaggr3g470r/forms.py:121 +#: pyaggr3g470r/forms.py:42 pyaggr3g470r/forms.py:99 pyaggr3g470r/forms.py:133 #: pyaggr3g470r/templates/admin/dashboard.html:13 msgid "Email" msgstr "" -#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:60 pyaggr3g470r/forms.py:121 +#: pyaggr3g470r/forms.py:45 pyaggr3g470r/forms.py:65 pyaggr3g470r/forms.py:136 msgid "Please enter your email address." msgstr "" -#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:61 pyaggr3g470r/forms.py:101 +#: pyaggr3g470r/forms.py:46 pyaggr3g470r/forms.py:66 pyaggr3g470r/forms.py:102 msgid "Password" msgstr "" -#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:61 +#: pyaggr3g470r/forms.py:47 pyaggr3g470r/forms.py:67 msgid "Please enter a password." msgstr "" -#: pyaggr3g470r/forms.py:43 pyaggr3g470r/templates/login.html:26 +#: pyaggr3g470r/forms.py:50 pyaggr3g470r/templates/login.html:26 msgid "Sign up" msgstr "" -#: pyaggr3g470r/forms.py:52 pyaggr3g470r/forms.py:111 +#: pyaggr3g470r/forms.py:55 pyaggr3g470r/forms.py:117 msgid "" "This nickname has invalid characters. Please use letters, numbers, dots " "and underscores only." msgstr "" -#: pyaggr3g470r/forms.py:62 pyaggr3g470r/templates/login.html:5 +#: pyaggr3g470r/forms.py:69 pyaggr3g470r/templates/login.html:5 msgid "Log In" msgstr "" -#: pyaggr3g470r/forms.py:75 +#: pyaggr3g470r/forms.py:80 msgid "Account not confirmed" msgstr "" -#: pyaggr3g470r/forms.py:78 +#: pyaggr3g470r/forms.py:83 msgid "Invalid email or password" msgstr "" -#: pyaggr3g470r/forms.py:83 pyaggr3g470r/templates/feeds.html:11 +#: pyaggr3g470r/forms.py:89 pyaggr3g470r/templates/feeds.html:11 msgid "Title" msgstr "" -#: pyaggr3g470r/forms.py:84 pyaggr3g470r/templates/admin/user.html:27 +#: pyaggr3g470r/forms.py:90 pyaggr3g470r/templates/admin/user.html:27 msgid "Feed link" msgstr "" -#: pyaggr3g470r/forms.py:85 pyaggr3g470r/templates/admin/user.html:28 +#: pyaggr3g470r/forms.py:91 pyaggr3g470r/templates/admin/user.html:28 msgid "Site link" msgstr "" -#: pyaggr3g470r/forms.py:86 -msgid "Email notification" -msgstr "" - -#: pyaggr3g470r/forms.py:87 +#: pyaggr3g470r/forms.py:92 msgid "Check for updates" msgstr "" -#: pyaggr3g470r/forms.py:88 pyaggr3g470r/forms.py:102 +#: pyaggr3g470r/forms.py:93 pyaggr3g470r/forms.py:107 msgid "Save" msgstr "" -#: pyaggr3g470r/forms.py:100 +#: pyaggr3g470r/forms.py:101 msgid "Please enter your email." msgstr "" -#: pyaggr3g470r/forms.py:116 +#: pyaggr3g470r/forms.py:103 +msgid "Password Confirmation" +msgstr "" + +#: pyaggr3g470r/forms.py:104 +msgid "Feeds refresh frequency (in minutes)" +msgstr "" + +#: pyaggr3g470r/forms.py:112 +msgid "Passwords aren't the same." +msgstr "" + +#: pyaggr3g470r/forms.py:125 msgid "Subject" msgstr "" -#: pyaggr3g470r/forms.py:116 +#: pyaggr3g470r/forms.py:126 msgid "Please enter a subject." msgstr "" -#: pyaggr3g470r/forms.py:117 +#: pyaggr3g470r/forms.py:127 msgid "Message" msgstr "" -#: pyaggr3g470r/forms.py:117 +#: pyaggr3g470r/forms.py:128 msgid "Please enter a content." msgstr "" -#: pyaggr3g470r/forms.py:118 +#: pyaggr3g470r/forms.py:129 msgid "Send" msgstr "" -#: pyaggr3g470r/forms.py:122 +#: pyaggr3g470r/forms.py:137 msgid "Recover" msgstr "" -#: pyaggr3g470r/forms.py:135 +#: pyaggr3g470r/forms.py:147 msgid "Account not confirmed." msgstr "" -#: pyaggr3g470r/forms.py:138 +#: pyaggr3g470r/forms.py:150 msgid "Invalid email." msgstr "" -#: pyaggr3g470r/views.py:99 -msgid "Authentication required." -msgstr "" - -#: pyaggr3g470r/views.py:104 -msgid "Forbidden." -msgstr "" - -#: pyaggr3g470r/views.py:156 -msgid "Logged in successfully." -msgstr "" - -#: pyaggr3g470r/views.py:178 -msgid "Logged out successfully." -msgstr "" - -#: pyaggr3g470r/views.py:187 -msgid "Self-registration is disabled." -msgstr "" - -#: pyaggr3g470r/views.py:204 -msgid "Email already used." -msgstr "" - -#: pyaggr3g470r/views.py:211 pyaggr3g470r/views.py:921 -msgid "Problem while sending activation email" -msgstr "" - -#: pyaggr3g470r/views.py:214 -msgid "Your account has been created. Check your mail to confirm it." -msgstr "" - -#: pyaggr3g470r/views.py:271 pyaggr3g470r/views.py:601 -msgid "Downloading articles..." -msgstr "" - -#: pyaggr3g470r/views.py:343 pyaggr3g470r/views.py:403 -msgid "This article do not exist." -msgstr "" - -#: pyaggr3g470r/views.py:400 pyaggr3g470r/templates/home.html:75 -msgid "Article" -msgstr "" - -#: pyaggr3g470r/views.py:400 -msgid "deleted." -msgstr "" - -#: pyaggr3g470r/views.py:499 -msgid "Indexing database..." -msgstr "" - -#: pyaggr3g470r/views.py:501 pyaggr3g470r/views.py:570 -msgid "An error occured" -msgstr "" - -#: pyaggr3g470r/views.py:504 -msgid "Option not available on Heroku." -msgstr "" - -#: pyaggr3g470r/views.py:519 pyaggr3g470r/views.py:529 -msgid "Error when exporting articles." -msgstr "" - -#: pyaggr3g470r/views.py:535 -msgid "Export format not supported." -msgstr "" - -#: pyaggr3g470r/views.py:558 -msgid "Full text search is not yet implemented for Heroku." -msgstr "" - -#: pyaggr3g470r/views.py:595 pyaggr3g470r/views.py:608 -#: pyaggr3g470r/views.py:616 -msgid "File not allowed." -msgstr "" - -#: pyaggr3g470r/views.py:600 -msgid "feeds imported." -msgstr "" - -#: pyaggr3g470r/views.py:603 -msgid "Impossible to import the new feeds." -msgstr "" - -#: pyaggr3g470r/views.py:612 -msgid "Account imported." -msgstr "" - -#: pyaggr3g470r/views.py:614 -msgid "Impossible to import the account." -msgstr "" - -#: pyaggr3g470r/views.py:652 -msgid "Feed successfully updated." -msgstr "" - -#: pyaggr3g470r/views.py:664 -msgid "Feed successfully created." -msgstr "" - -#: pyaggr3g470r/views.py:667 -msgid "Downloading articles for the new feed..." -msgstr "" - -#: pyaggr3g470r/views.py:671 -msgid "Feed already in the database." -msgstr "" - -#: pyaggr3g470r/views.py:677 -msgid "Edit the feed" -msgstr "" - -#: pyaggr3g470r/views.py:690 pyaggr3g470r/templates/layout.html:109 -msgid "Add a feed" -msgstr "" - -#: pyaggr3g470r/views.py:703 pyaggr3g470r/templates/home.html:74 -#: pyaggr3g470r/templates/admin/user.html:42 -msgid "Feed" -msgstr "" - -#: pyaggr3g470r/views.py:703 pyaggr3g470r/views.py:898 -msgid "successfully deleted." -msgstr "" - -#: pyaggr3g470r/views.py:721 pyaggr3g470r/views.py:848 -#: pyaggr3g470r/views.py:858 pyaggr3g470r/views.py:898 -msgid "User" -msgstr "" - -#: pyaggr3g470r/views.py:721 pyaggr3g470r/views.py:848 -msgid "successfully updated." -msgstr "" - -#: pyaggr3g470r/views.py:740 -msgid "Your account has been deleted." -msgstr "" - -#: pyaggr3g470r/views.py:742 pyaggr3g470r/views.py:884 -#: pyaggr3g470r/views.py:900 pyaggr3g470r/views.py:929 -msgid "This user does not exist." -msgstr "" - -#: pyaggr3g470r/views.py:756 -msgid "Articles deleted." -msgstr "" - -#: pyaggr3g470r/views.py:770 -msgid "Your account has been confirmed." -msgstr "" - -#: pyaggr3g470r/views.py:772 -msgid "Impossible to confirm this account." -msgstr "" - -#: pyaggr3g470r/views.py:796 -msgid "New password sent to your address." -msgstr "" - -#: pyaggr3g470r/views.py:798 -msgid "Problem while sending your new password." -msgstr "" - -#: pyaggr3g470r/views.py:823 -msgid "Problem while sending email" -msgstr "" - -#: pyaggr3g470r/views.py:858 -msgid "successfully created." -msgstr "" - -#: pyaggr3g470r/views.py:867 -msgid "Edit the user" -msgstr "" - -#: pyaggr3g470r/views.py:870 pyaggr3g470r/templates/admin/dashboard.html:45 -msgid "Add a new user" -msgstr "" - -#: pyaggr3g470r/views.py:919 pyaggr3g470r/views.py:926 -msgid "Account of the user" -msgstr "" - -#: pyaggr3g470r/views.py:919 -msgid "successfully activated." -msgstr "" - -#: pyaggr3g470r/views.py:926 -msgid "successfully disabled." -msgstr "" - -#: pyaggr3g470r/templates/about.html:5 pyaggr3g470r/templates/layout.html:126 -#: pyaggr3g470r/templates/layout.html:143 +#: pyaggr3g470r/templates/about.html:5 pyaggr3g470r/templates/layout.html:117 +#: pyaggr3g470r/templates/layout.html:134 msgid "About" msgstr "" @@ -368,8 +184,8 @@ msgstr "" #: pyaggr3g470r/templates/about.html:19 msgid "" "The documentation of the RESTful API is here." +"href=\"https://pyaggr3g470r.readthedocs.org/en/latest/web-" +"services.html\">here." msgstr "" #: pyaggr3g470r/templates/about.html:20 @@ -397,23 +213,23 @@ msgstr "" #: pyaggr3g470r/templates/article.html:11 #: pyaggr3g470r/templates/duplicates.html:19 #: pyaggr3g470r/templates/duplicates.html:20 -#: pyaggr3g470r/templates/home.html:89 +#: pyaggr3g470r/templates/home.html:90 msgid "Delete this article" msgstr "" -#: pyaggr3g470r/templates/article.html:13 pyaggr3g470r/templates/home.html:91 +#: pyaggr3g470r/templates/article.html:13 pyaggr3g470r/templates/home.html:92 msgid "One of your favorites" msgstr "" -#: pyaggr3g470r/templates/article.html:15 pyaggr3g470r/templates/home.html:93 +#: pyaggr3g470r/templates/article.html:15 pyaggr3g470r/templates/home.html:94 msgid "Click if you like this article" msgstr "" -#: pyaggr3g470r/templates/article.html:18 pyaggr3g470r/templates/home.html:96 +#: pyaggr3g470r/templates/article.html:18 pyaggr3g470r/templates/home.html:97 msgid "Mark this article as unread" msgstr "" -#: pyaggr3g470r/templates/article.html:20 pyaggr3g470r/templates/home.html:98 +#: pyaggr3g470r/templates/article.html:20 pyaggr3g470r/templates/home.html:99 msgid "Mark this article as read" msgstr "" @@ -451,26 +267,26 @@ msgstr "" msgid "More articles" msgstr "" -#: pyaggr3g470r/templates/favorites.html:17 pyaggr3g470r/templates/home.html:29 -#: pyaggr3g470r/templates/home.html:44 pyaggr3g470r/templates/unread.html:17 +#: pyaggr3g470r/templates/favorites.html:17 pyaggr3g470r/templates/home.html:32 +#: pyaggr3g470r/templates/home.html:50 pyaggr3g470r/templates/unread.html:17 msgid "Details" msgstr "" #: pyaggr3g470r/templates/favorites.html:18 pyaggr3g470r/templates/feed.html:8 -#: pyaggr3g470r/templates/feeds.html:33 pyaggr3g470r/templates/home.html:31 -#: pyaggr3g470r/templates/home.html:46 pyaggr3g470r/templates/unread.html:18 +#: pyaggr3g470r/templates/feeds.html:33 pyaggr3g470r/templates/home.html:34 +#: pyaggr3g470r/templates/home.html:52 pyaggr3g470r/templates/unread.html:18 #: pyaggr3g470r/templates/admin/user.html:43 msgid "Edit this feed" msgstr "" #: pyaggr3g470r/templates/feed.html:7 pyaggr3g470r/templates/feeds.html:35 -#: pyaggr3g470r/templates/home.html:32 pyaggr3g470r/templates/home.html:47 +#: pyaggr3g470r/templates/home.html:35 pyaggr3g470r/templates/home.html:53 #: pyaggr3g470r/templates/admin/user.html:44 msgid "Delete this feed" msgstr "" #: pyaggr3g470r/templates/feed.html:7 pyaggr3g470r/templates/feeds.html:35 -#: pyaggr3g470r/templates/home.html:32 pyaggr3g470r/templates/home.html:47 +#: pyaggr3g470r/templates/home.html:35 pyaggr3g470r/templates/home.html:53 #: pyaggr3g470r/templates/admin/user.html:44 msgid "You are going to delete this feed." msgstr "" @@ -487,31 +303,51 @@ msgstr "" msgid "of the database" msgstr "" -#: pyaggr3g470r/templates/feed.html:17 +#: pyaggr3g470r/templates/feed.html:18 +msgid "Last download:" +msgstr "" + +#: pyaggr3g470r/templates/feed.html:22 +msgid "" +"That feed has encountered too much consecutive errors and won't be " +"retrieved anymore." +msgstr "" + +#: pyaggr3g470r/templates/feed.html:24 +msgid "" +"The download of this feed has encountered some problems. However its " +"error counter will be reinitialized at the next successful retrieving." +msgstr "" + +#: pyaggr3g470r/templates/feed.html:28 +msgid "Here's the last error encountered while retrieving this feed:" +msgstr "" + +#: pyaggr3g470r/templates/feed.html:31 msgid "Address of the feed" msgstr "" -#: pyaggr3g470r/templates/feed.html:19 +#: pyaggr3g470r/templates/feed.html:33 msgid "Address of the site" msgstr "" -#: pyaggr3g470r/templates/feed.html:23 +#: pyaggr3g470r/templates/feed.html:37 msgid "The last article was posted" msgstr "" -#: pyaggr3g470r/templates/feed.html:23 +#: pyaggr3g470r/templates/feed.html:37 msgid "day(s) ago." msgstr "" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "Daily average" msgstr "" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "between the" msgstr "" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "and the" msgstr "" @@ -540,8 +376,8 @@ msgid "Site" msgstr "" #: pyaggr3g470r/templates/feeds.html:13 pyaggr3g470r/templates/feeds.html:32 -#: pyaggr3g470r/templates/home.html:30 pyaggr3g470r/templates/home.html:45 -#: pyaggr3g470r/templates/layout.html:104 +#: pyaggr3g470r/templates/home.html:33 pyaggr3g470r/templates/home.html:51 +#: pyaggr3g470r/templates/layout.html:95 msgid "Articles" msgstr "" @@ -580,31 +416,40 @@ msgstr "" msgid "upload an OPML file." msgstr "" -#: pyaggr3g470r/templates/home.html:18 pyaggr3g470r/templates/layout.html:118 +#: pyaggr3g470r/templates/home.html:18 pyaggr3g470r/templates/layout.html:109 msgid "All feeds" msgstr "" -#: pyaggr3g470r/templates/home.html:33 pyaggr3g470r/templates/home.html:48 +#: pyaggr3g470r/templates/home.html:36 pyaggr3g470r/templates/home.html:54 msgid "Mark this feed as read" msgstr "" -#: pyaggr3g470r/templates/home.html:34 pyaggr3g470r/templates/home.html:49 +#: pyaggr3g470r/templates/home.html:37 pyaggr3g470r/templates/home.html:55 msgid "Mark this feed as unread" msgstr "" -#: pyaggr3g470r/templates/home.html:57 pyaggr3g470r/templates/home.html:65 +#: pyaggr3g470r/templates/home.html:63 pyaggr3g470r/templates/home.html:71 msgid "All" msgstr "" -#: pyaggr3g470r/templates/home.html:58 +#: pyaggr3g470r/templates/home.html:64 msgid "Read" msgstr "" -#: pyaggr3g470r/templates/home.html:59 pyaggr3g470r/templates/layout.html:115 +#: pyaggr3g470r/templates/home.html:65 pyaggr3g470r/templates/layout.html:106 msgid "Unread" msgstr "" -#: pyaggr3g470r/templates/home.html:76 +#: pyaggr3g470r/templates/home.html:81 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:622 +msgid "Feed" +msgstr "" + +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:333 +msgid "Article" +msgstr "" + +#: pyaggr3g470r/templates/home.html:83 msgid "Date" msgstr "" @@ -620,39 +465,43 @@ msgstr "" msgid "No inactive feeds." msgstr "" -#: pyaggr3g470r/templates/layout.html:106 +#: pyaggr3g470r/templates/layout.html:97 msgid "Fetch" msgstr "" -#: pyaggr3g470r/templates/layout.html:107 +#: pyaggr3g470r/templates/layout.html:98 msgid "Mark all as read" msgstr "" -#: pyaggr3g470r/templates/layout.html:113 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:609 +msgid "Add a feed" +msgstr "" + +#: pyaggr3g470r/templates/layout.html:104 msgid "Filter" msgstr "" -#: pyaggr3g470r/templates/layout.html:116 +#: pyaggr3g470r/templates/layout.html:107 msgid "Favorites" msgstr "" -#: pyaggr3g470r/templates/layout.html:117 +#: pyaggr3g470r/templates/layout.html:108 msgid "Inactive feeds" msgstr "" -#: pyaggr3g470r/templates/layout.html:119 +#: pyaggr3g470r/templates/layout.html:110 msgid "History" msgstr "" -#: pyaggr3g470r/templates/layout.html:122 +#: pyaggr3g470r/templates/layout.html:113 msgid "Management" msgstr "" -#: pyaggr3g470r/templates/layout.html:124 +#: pyaggr3g470r/templates/layout.html:115 msgid "Dashboard" msgstr "" -#: pyaggr3g470r/templates/layout.html:127 +#: pyaggr3g470r/templates/layout.html:118 msgid "Logout" msgstr "" @@ -804,6 +653,11 @@ msgstr "" msgid "You are going to delete this account." msgstr "" +#: pyaggr3g470r/templates/admin/dashboard.html:45 +#: pyaggr3g470r/views/views.py:789 +msgid "Add a new user" +msgstr "" + #: pyaggr3g470r/templates/admin/dashboard.html:46 msgid "Send notification messages" msgstr "" @@ -828,3 +682,178 @@ msgstr "" msgid "Number of articles" msgstr "" +#: pyaggr3g470r/views/views.py:104 +msgid "Authentication required." +msgstr "" + +#: pyaggr3g470r/views/views.py:109 +msgid "Forbidden." +msgstr "" + +#: pyaggr3g470r/views/views.py:162 +msgid "Logged in successfully." +msgstr "" + +#: pyaggr3g470r/views/views.py:185 +msgid "Logged out successfully." +msgstr "" + +#: pyaggr3g470r/views/views.py:194 +msgid "Self-registration is disabled." +msgstr "" + +#: pyaggr3g470r/views/views.py:211 +msgid "Email already used." +msgstr "" + +#: pyaggr3g470r/views/views.py:218 pyaggr3g470r/views/views.py:840 +msgid "Problem while sending activation email" +msgstr "" + +#: pyaggr3g470r/views/views.py:221 +msgid "Your account has been created. Check your mail to confirm it." +msgstr "" + +#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:516 +msgid "Downloading articles..." +msgstr "" + +#: pyaggr3g470r/views/views.py:333 +msgid "deleted." +msgstr "" + +#: pyaggr3g470r/views/views.py:336 +msgid "This article do not exist." +msgstr "" + +#: pyaggr3g470r/views/views.py:414 +msgid "Indexing database..." +msgstr "" + +#: pyaggr3g470r/views/views.py:416 pyaggr3g470r/views/views.py:485 +msgid "An error occured" +msgstr "" + +#: pyaggr3g470r/views/views.py:419 +msgid "Option not available on Heroku." +msgstr "" + +#: pyaggr3g470r/views/views.py:434 pyaggr3g470r/views/views.py:444 +msgid "Error when exporting articles." +msgstr "" + +#: pyaggr3g470r/views/views.py:450 +msgid "Export format not supported." +msgstr "" + +#: pyaggr3g470r/views/views.py:473 +msgid "Full text search is not yet implemented for Heroku." +msgstr "" + +#: pyaggr3g470r/views/views.py:510 pyaggr3g470r/views/views.py:523 +#: pyaggr3g470r/views/views.py:531 +msgid "File not allowed." +msgstr "" + +#: pyaggr3g470r/views/views.py:515 +msgid "feeds imported." +msgstr "" + +#: pyaggr3g470r/views/views.py:518 +msgid "Impossible to import the new feeds." +msgstr "" + +#: pyaggr3g470r/views/views.py:527 +msgid "Account imported." +msgstr "" + +#: pyaggr3g470r/views/views.py:529 +msgid "Impossible to import the account." +msgstr "" + +#: pyaggr3g470r/views/views.py:571 +msgid "Feed successfully updated." +msgstr "" + +#: pyaggr3g470r/views/views.py:582 +msgid "Feed successfully created." +msgstr "" + +#: pyaggr3g470r/views/views.py:585 +msgid "Downloading articles for the new feed..." +msgstr "" + +#: pyaggr3g470r/views/views.py:589 +msgid "Feed already in the database." +msgstr "" + +#: pyaggr3g470r/views/views.py:596 +msgid "Edit the feed" +msgstr "" + +#: pyaggr3g470r/views/views.py:622 pyaggr3g470r/views/views.py:817 +msgid "successfully deleted." +msgstr "" + +#: pyaggr3g470r/views/views.py:640 pyaggr3g470r/views/views.py:767 +#: pyaggr3g470r/views/views.py:777 pyaggr3g470r/views/views.py:817 +msgid "User" +msgstr "" + +#: pyaggr3g470r/views/views.py:641 pyaggr3g470r/views/views.py:767 +msgid "successfully updated." +msgstr "" + +#: pyaggr3g470r/views/views.py:661 +msgid "Your account has been deleted." +msgstr "" + +#: pyaggr3g470r/views/views.py:663 pyaggr3g470r/views/views.py:803 +#: pyaggr3g470r/views/views.py:819 pyaggr3g470r/views/views.py:847 +msgid "This user does not exist." +msgstr "" + +#: pyaggr3g470r/views/views.py:677 +msgid "Articles deleted." +msgstr "" + +#: pyaggr3g470r/views/views.py:691 +msgid "Your account has been confirmed." +msgstr "" + +#: pyaggr3g470r/views/views.py:693 +msgid "Impossible to confirm this account." +msgstr "" + +#: pyaggr3g470r/views/views.py:715 +msgid "New password sent to your address." +msgstr "" + +#: pyaggr3g470r/views/views.py:717 +msgid "Problem while sending your new password." +msgstr "" + +#: pyaggr3g470r/views/views.py:742 +msgid "Problem while sending email" +msgstr "" + +#: pyaggr3g470r/views/views.py:777 +msgid "successfully created." +msgstr "" + +#: pyaggr3g470r/views/views.py:786 +msgid "Edit the user" +msgstr "" + +#: pyaggr3g470r/views/views.py:838 pyaggr3g470r/views/views.py:844 +msgid "Account of the user" +msgstr "" + +#: pyaggr3g470r/views/views.py:838 +msgid "successfully activated." +msgstr "" + +#: pyaggr3g470r/views/views.py:844 +msgid "successfully disabled." +msgstr "" + diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index e3b7f0ff..5ac1b770 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index 3bb25cb9..81af46ed 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-01-09 22:12+0100\n" -"PO-Revision-Date: 2015-01-09 22:13+0100\n" +"POT-Creation-Date: 2015-03-08 17:28+0100\n" +"PO-Revision-Date: 2015-03-08 17:34+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -19,37 +19,37 @@ msgstr "" "Generated-By: Babel 1.3\n" "X-Generator: Poedit 1.5.4\n" -#: pyaggr3g470r/forms.py:39 pyaggr3g470r/forms.py:99 +#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:97 #: pyaggr3g470r/templates/admin/dashboard.html:12 msgid "Nickname" msgstr "Pseudonyme" -#: pyaggr3g470r/forms.py:39 pyaggr3g470r/forms.py:99 +#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:98 msgid "Please enter your nickname." msgstr "S'il vous plaît, entrez votre pseudonyme." -#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:100 -#: pyaggr3g470r/forms.py:121 pyaggr3g470r/templates/admin/dashboard.html:13 +#: pyaggr3g470r/forms.py:42 pyaggr3g470r/forms.py:99 pyaggr3g470r/forms.py:133 +#: pyaggr3g470r/templates/admin/dashboard.html:13 msgid "Email" msgstr "Email" -#: pyaggr3g470r/forms.py:40 pyaggr3g470r/forms.py:60 pyaggr3g470r/forms.py:121 +#: pyaggr3g470r/forms.py:45 pyaggr3g470r/forms.py:65 pyaggr3g470r/forms.py:136 msgid "Please enter your email address." msgstr "S'il vous plaît, entrez votre adresse email." -#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:61 pyaggr3g470r/forms.py:101 +#: pyaggr3g470r/forms.py:46 pyaggr3g470r/forms.py:66 pyaggr3g470r/forms.py:102 msgid "Password" msgstr "Mot de passe" -#: pyaggr3g470r/forms.py:41 pyaggr3g470r/forms.py:61 +#: pyaggr3g470r/forms.py:47 pyaggr3g470r/forms.py:67 msgid "Please enter a password." msgstr "S'il vous plaît entrer un mot de passe." -#: pyaggr3g470r/forms.py:43 pyaggr3g470r/templates/login.html:26 +#: pyaggr3g470r/forms.py:50 pyaggr3g470r/templates/login.html:26 msgid "Sign up" msgstr "S'inscrire" -#: pyaggr3g470r/forms.py:52 pyaggr3g470r/forms.py:111 +#: pyaggr3g470r/forms.py:55 pyaggr3g470r/forms.py:117 msgid "" "This nickname has invalid characters. Please use letters, numbers, dots and " "underscores only." @@ -57,272 +57,88 @@ msgstr "" "Ce pseudonyme a des caractères non valides. Utilisez seulement des lettres, " "des chiffres, des points et '_'." -#: pyaggr3g470r/forms.py:62 pyaggr3g470r/templates/login.html:5 +#: pyaggr3g470r/forms.py:69 pyaggr3g470r/templates/login.html:5 msgid "Log In" msgstr "Connexion" -#: pyaggr3g470r/forms.py:75 +#: pyaggr3g470r/forms.py:80 msgid "Account not confirmed" msgstr "Compte non confirmé" -#: pyaggr3g470r/forms.py:78 +#: pyaggr3g470r/forms.py:83 msgid "Invalid email or password" msgstr "E-mail ou mot de passe invalide" -#: pyaggr3g470r/forms.py:83 pyaggr3g470r/templates/feeds.html:11 +#: pyaggr3g470r/forms.py:89 pyaggr3g470r/templates/feeds.html:11 msgid "Title" msgstr "Titre" -#: pyaggr3g470r/forms.py:84 pyaggr3g470r/templates/admin/user.html:27 +#: pyaggr3g470r/forms.py:90 pyaggr3g470r/templates/admin/user.html:27 msgid "Feed link" msgstr "Lien du flux" -#: pyaggr3g470r/forms.py:85 pyaggr3g470r/templates/admin/user.html:28 +#: pyaggr3g470r/forms.py:91 pyaggr3g470r/templates/admin/user.html:28 msgid "Site link" msgstr "Lien du site" -#: pyaggr3g470r/forms.py:86 -msgid "Email notification" -msgstr "Notification par email" - -#: pyaggr3g470r/forms.py:87 +#: pyaggr3g470r/forms.py:92 msgid "Check for updates" msgstr "Vérifier les mises à jour" -#: pyaggr3g470r/forms.py:88 pyaggr3g470r/forms.py:102 +#: pyaggr3g470r/forms.py:93 pyaggr3g470r/forms.py:107 msgid "Save" msgstr "Sauver" -#: pyaggr3g470r/forms.py:100 +#: pyaggr3g470r/forms.py:101 msgid "Please enter your email." msgstr "S'il vous plaît, entrez votre email." -#: pyaggr3g470r/forms.py:116 +#: pyaggr3g470r/forms.py:103 +msgid "Password Confirmation" +msgstr "Confirmation du mot de passe" + +#: pyaggr3g470r/forms.py:104 +msgid "Feeds refresh frequency (in minutes)" +msgstr "Fréquence de rafraîchissement du flux (en minutes)" + +#: pyaggr3g470r/forms.py:112 +msgid "Passwords aren't the same." +msgstr "Les mots de passe ne sont pas identiques." + +#: pyaggr3g470r/forms.py:125 msgid "Subject" msgstr "Objet" -#: pyaggr3g470r/forms.py:116 +#: pyaggr3g470r/forms.py:126 msgid "Please enter a subject." msgstr "S'il vous plaît entrer un objet." -#: pyaggr3g470r/forms.py:117 +#: pyaggr3g470r/forms.py:127 msgid "Message" msgstr "Message" -#: pyaggr3g470r/forms.py:117 +#: pyaggr3g470r/forms.py:128 msgid "Please enter a content." msgstr "S'il vous plaît entrer un contenu." -#: pyaggr3g470r/forms.py:118 +#: pyaggr3g470r/forms.py:129 msgid "Send" msgstr "Envoyer" -#: pyaggr3g470r/forms.py:122 +#: pyaggr3g470r/forms.py:137 msgid "Recover" msgstr "Récupérer" -#: pyaggr3g470r/forms.py:135 +#: pyaggr3g470r/forms.py:147 msgid "Account not confirmed." msgstr "Compte non confirmé." -#: pyaggr3g470r/forms.py:138 +#: pyaggr3g470r/forms.py:150 msgid "Invalid email." msgstr "Email invalide." -#: pyaggr3g470r/views.py:99 -msgid "Authentication required." -msgstr "Authentification requise." - -#: pyaggr3g470r/views.py:104 -msgid "Forbidden." -msgstr "Interdit." - -#: pyaggr3g470r/views.py:156 -msgid "Logged in successfully." -msgstr "Connecté avec succès." - -#: pyaggr3g470r/views.py:178 -msgid "Logged out successfully." -msgstr "Déconnecté avec succès." - -#: pyaggr3g470r/views.py:187 -msgid "Self-registration is disabled." -msgstr "L'auto-enregistrement est désactivé." - -#: pyaggr3g470r/views.py:204 -msgid "Email already used." -msgstr "Email déjà utilisé." - -#: pyaggr3g470r/views.py:211 pyaggr3g470r/views.py:921 -msgid "Problem while sending activation email" -msgstr "Problème lors de l'envoi d'email d'activation" - -#: pyaggr3g470r/views.py:214 -msgid "Your account has been created. Check your mail to confirm it." -msgstr "Votre compte a été créé. Vérifiez votre courrier pour le confirmer." - -#: pyaggr3g470r/views.py:271 pyaggr3g470r/views.py:601 -msgid "Downloading articles..." -msgstr "Téléchargement des articles." - -#: pyaggr3g470r/views.py:343 pyaggr3g470r/views.py:403 -msgid "This article do not exist." -msgstr "Cet article n'existe pas." - -#: pyaggr3g470r/views.py:400 pyaggr3g470r/templates/home.html:75 -msgid "Article" -msgstr "Article" - -#: pyaggr3g470r/views.py:400 -msgid "deleted." -msgstr "supprimé." - -#: pyaggr3g470r/views.py:499 -msgid "Indexing database..." -msgstr "Indexation la base de données..." - -#: pyaggr3g470r/views.py:501 pyaggr3g470r/views.py:570 -msgid "An error occured" -msgstr "Une erreur est survenue." - -#: pyaggr3g470r/views.py:504 -msgid "Option not available on Heroku." -msgstr "Option non disponible sur Heroku." - -#: pyaggr3g470r/views.py:519 pyaggr3g470r/views.py:529 -msgid "Error when exporting articles." -msgstr "Erreur lors de l'export des articles." - -#: pyaggr3g470r/views.py:535 -msgid "Export format not supported." -msgstr "Ce format d'export n'est pas supporté." - -#: pyaggr3g470r/views.py:558 -msgid "Full text search is not yet implemented for Heroku." -msgstr "La recherche rapide n'est pas supporté sur Heroku." - -#: pyaggr3g470r/views.py:595 pyaggr3g470r/views.py:608 -#: pyaggr3g470r/views.py:616 -msgid "File not allowed." -msgstr "Fichier non autorisé." - -#: pyaggr3g470r/views.py:600 -msgid "feeds imported." -msgstr "flux importés." - -#: pyaggr3g470r/views.py:603 -msgid "Impossible to import the new feeds." -msgstr "Impossible d'importer les nouveaux flux." - -#: pyaggr3g470r/views.py:612 -msgid "Account imported." -msgstr "Compte importé." - -#: pyaggr3g470r/views.py:614 -msgid "Impossible to import the account." -msgstr "Impossible d'importer le compte." - -#: pyaggr3g470r/views.py:652 -msgid "Feed successfully updated." -msgstr "Flux mis à jour avec succès." - -#: pyaggr3g470r/views.py:664 -msgid "Feed successfully created." -msgstr "Flux créé avec succès." - -#: pyaggr3g470r/views.py:667 -msgid "Downloading articles for the new feed..." -msgstr "Téléchargement des articles du nouveau flux..." - -#: pyaggr3g470r/views.py:671 -msgid "Feed already in the database." -msgstr "Flux déjà dans la base de données." - -#: pyaggr3g470r/views.py:677 -msgid "Edit the feed" -msgstr "Éditez ce flux" - -#: pyaggr3g470r/views.py:690 pyaggr3g470r/templates/layout.html:109 -msgid "Add a feed" -msgstr "Ajouter un flux" - -#: pyaggr3g470r/views.py:703 pyaggr3g470r/templates/home.html:74 -#: pyaggr3g470r/templates/admin/user.html:42 -msgid "Feed" -msgstr "Flux" - -#: pyaggr3g470r/views.py:703 pyaggr3g470r/views.py:898 -msgid "successfully deleted." -msgstr "supprimé avec succès." - -#: pyaggr3g470r/views.py:721 pyaggr3g470r/views.py:848 -#: pyaggr3g470r/views.py:858 pyaggr3g470r/views.py:898 -msgid "User" -msgstr "Utilisateur" - -#: pyaggr3g470r/views.py:721 pyaggr3g470r/views.py:848 -msgid "successfully updated." -msgstr "mis à jour avec succès." - -#: pyaggr3g470r/views.py:740 -msgid "Your account has been deleted." -msgstr "Votre compte a été supprimé." - -#: pyaggr3g470r/views.py:742 pyaggr3g470r/views.py:884 -#: pyaggr3g470r/views.py:900 pyaggr3g470r/views.py:929 -msgid "This user does not exist." -msgstr "Cet utilisateur n'existe pas." - -#: pyaggr3g470r/views.py:756 -msgid "Articles deleted." -msgstr "Articles supprimés." - -#: pyaggr3g470r/views.py:770 -msgid "Your account has been confirmed." -msgstr "Votre compte a été confirmé." - -#: pyaggr3g470r/views.py:772 -msgid "Impossible to confirm this account." -msgstr "Impossible de confirmer ce compte." - -#: pyaggr3g470r/views.py:796 -msgid "New password sent to your address." -msgstr "Nouveau mot de passe envoyé à votre adresse." - -#: pyaggr3g470r/views.py:798 -msgid "Problem while sending your new password." -msgstr "Problème lors de l'envoi de votre nouveau mot de passe." - -#: pyaggr3g470r/views.py:823 -msgid "Problem while sending email" -msgstr "Problème lors de l'envoi de l'email" - -#: pyaggr3g470r/views.py:858 -msgid "successfully created." -msgstr "créé avec succès." - -#: pyaggr3g470r/views.py:867 -msgid "Edit the user" -msgstr "Éditer cet utilisateur" - -#: pyaggr3g470r/views.py:870 pyaggr3g470r/templates/admin/dashboard.html:45 -msgid "Add a new user" -msgstr "Ajouter un nouvel utilisateur" - -#: pyaggr3g470r/views.py:919 pyaggr3g470r/views.py:926 -msgid "Account of the user" -msgstr "Compte de l'utilisateur" - -#: pyaggr3g470r/views.py:919 -msgid "successfully activated." -msgstr "activé avec succès." - -#: pyaggr3g470r/views.py:926 -msgid "successfully disabled." -msgstr "désactivé avec succès." - -#: pyaggr3g470r/templates/about.html:5 pyaggr3g470r/templates/layout.html:126 -#: pyaggr3g470r/templates/layout.html:143 +#: pyaggr3g470r/templates/about.html:5 pyaggr3g470r/templates/layout.html:117 +#: pyaggr3g470r/templates/layout.html:134 msgid "About" msgstr "À propos" @@ -379,11 +195,11 @@ msgstr "" #: pyaggr3g470r/templates/about.html:19 msgid "" -"The documentation of the RESTful API is here." +"The documentation of the RESTful API is here." msgstr "" -"La documentation de l'API RESTful est ici." +"La documentation de l'API RESTful est ici." #: pyaggr3g470r/templates/about.html:20 #, python-format @@ -416,23 +232,23 @@ msgstr "de" #: pyaggr3g470r/templates/article.html:11 #: pyaggr3g470r/templates/duplicates.html:19 #: pyaggr3g470r/templates/duplicates.html:20 -#: pyaggr3g470r/templates/home.html:89 +#: pyaggr3g470r/templates/home.html:90 msgid "Delete this article" msgstr "Supprimer cet article" -#: pyaggr3g470r/templates/article.html:13 pyaggr3g470r/templates/home.html:91 +#: pyaggr3g470r/templates/article.html:13 pyaggr3g470r/templates/home.html:92 msgid "One of your favorites" msgstr "Un de vos favoris" -#: pyaggr3g470r/templates/article.html:15 pyaggr3g470r/templates/home.html:93 +#: pyaggr3g470r/templates/article.html:15 pyaggr3g470r/templates/home.html:94 msgid "Click if you like this article" msgstr "Cliquez si vous aimez cet article" -#: pyaggr3g470r/templates/article.html:18 pyaggr3g470r/templates/home.html:96 +#: pyaggr3g470r/templates/article.html:18 pyaggr3g470r/templates/home.html:97 msgid "Mark this article as unread" msgstr "Marquer cet article comme non lu" -#: pyaggr3g470r/templates/article.html:20 pyaggr3g470r/templates/home.html:98 +#: pyaggr3g470r/templates/article.html:20 pyaggr3g470r/templates/home.html:99 msgid "Mark this article as read" msgstr "Marquer cet article comme lu" @@ -471,26 +287,26 @@ msgid "More articles" msgstr "Plus d'articles" #: pyaggr3g470r/templates/favorites.html:17 -#: pyaggr3g470r/templates/home.html:29 pyaggr3g470r/templates/home.html:44 +#: pyaggr3g470r/templates/home.html:32 pyaggr3g470r/templates/home.html:50 #: pyaggr3g470r/templates/unread.html:17 msgid "Details" msgstr "Détails" #: pyaggr3g470r/templates/favorites.html:18 pyaggr3g470r/templates/feed.html:8 -#: pyaggr3g470r/templates/feeds.html:33 pyaggr3g470r/templates/home.html:31 -#: pyaggr3g470r/templates/home.html:46 pyaggr3g470r/templates/unread.html:18 +#: pyaggr3g470r/templates/feeds.html:33 pyaggr3g470r/templates/home.html:34 +#: pyaggr3g470r/templates/home.html:52 pyaggr3g470r/templates/unread.html:18 #: pyaggr3g470r/templates/admin/user.html:43 msgid "Edit this feed" msgstr "Éditer ce flux" #: pyaggr3g470r/templates/feed.html:7 pyaggr3g470r/templates/feeds.html:35 -#: pyaggr3g470r/templates/home.html:32 pyaggr3g470r/templates/home.html:47 +#: pyaggr3g470r/templates/home.html:35 pyaggr3g470r/templates/home.html:53 #: pyaggr3g470r/templates/admin/user.html:44 msgid "Delete this feed" msgstr "Supprimer ce flux" #: pyaggr3g470r/templates/feed.html:7 pyaggr3g470r/templates/feeds.html:35 -#: pyaggr3g470r/templates/home.html:32 pyaggr3g470r/templates/home.html:47 +#: pyaggr3g470r/templates/home.html:35 pyaggr3g470r/templates/home.html:53 #: pyaggr3g470r/templates/admin/user.html:44 msgid "You are going to delete this feed." msgstr "Vous allez supprimer ce flux." @@ -507,31 +323,55 @@ msgstr "articles" msgid "of the database" msgstr "de la base de données" -#: pyaggr3g470r/templates/feed.html:17 +#: pyaggr3g470r/templates/feed.html:18 +msgid "Last download:" +msgstr "Dernier téléchargement:" + +#: pyaggr3g470r/templates/feed.html:22 +msgid "" +"That feed has encountered too much consecutive errors and won't be retrieved " +"anymore." +msgstr "" +"Ce flux a rencontré trop d'erreurs consécutives et ne sera plus récupéré." + +#: pyaggr3g470r/templates/feed.html:24 +msgid "" +"The download of this feed has encountered some problems. However its error " +"counter will be reinitialized at the next successful retrieving." +msgstr "" +"Le téléchargement de ce flux a rencontré quelques problèmes. Cependant, son " +"compteur d'erreurs sera réinitialisé lors de la prochaine récupération " +"réussie." + +#: pyaggr3g470r/templates/feed.html:28 +msgid "Here's the last error encountered while retrieving this feed:" +msgstr "Voici la dernière erreur survenue lors de la récupération ce flux:" + +#: pyaggr3g470r/templates/feed.html:31 msgid "Address of the feed" msgstr "Adresse du flux" -#: pyaggr3g470r/templates/feed.html:19 +#: pyaggr3g470r/templates/feed.html:33 msgid "Address of the site" msgstr "Adresse du site" -#: pyaggr3g470r/templates/feed.html:23 +#: pyaggr3g470r/templates/feed.html:37 msgid "The last article was posted" msgstr "Le dernier article a été posté il y a" -#: pyaggr3g470r/templates/feed.html:23 +#: pyaggr3g470r/templates/feed.html:37 msgid "day(s) ago." msgstr "jours." -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "Daily average" msgstr "Moyenne journalière" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "between the" msgstr "entre le" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:38 msgid "and the" msgstr "et le" @@ -564,8 +404,8 @@ msgid "Site" msgstr "Site" #: pyaggr3g470r/templates/feeds.html:13 pyaggr3g470r/templates/feeds.html:32 -#: pyaggr3g470r/templates/home.html:30 pyaggr3g470r/templates/home.html:45 -#: pyaggr3g470r/templates/layout.html:104 +#: pyaggr3g470r/templates/home.html:33 pyaggr3g470r/templates/home.html:51 +#: pyaggr3g470r/templates/layout.html:95 msgid "Articles" msgstr "Articles" @@ -604,31 +444,40 @@ msgstr "ou" msgid "upload an OPML file." msgstr "téléchargez un fichier OPML." -#: pyaggr3g470r/templates/home.html:18 pyaggr3g470r/templates/layout.html:118 +#: pyaggr3g470r/templates/home.html:18 pyaggr3g470r/templates/layout.html:109 msgid "All feeds" msgstr "Tous les flux" -#: pyaggr3g470r/templates/home.html:33 pyaggr3g470r/templates/home.html:48 +#: pyaggr3g470r/templates/home.html:36 pyaggr3g470r/templates/home.html:54 msgid "Mark this feed as read" msgstr "Marquer ce flux comme lu" -#: pyaggr3g470r/templates/home.html:34 pyaggr3g470r/templates/home.html:49 +#: pyaggr3g470r/templates/home.html:37 pyaggr3g470r/templates/home.html:55 msgid "Mark this feed as unread" msgstr "Marquer ce flux comme non lu" -#: pyaggr3g470r/templates/home.html:57 pyaggr3g470r/templates/home.html:65 +#: pyaggr3g470r/templates/home.html:63 pyaggr3g470r/templates/home.html:71 msgid "All" msgstr "Tout" -#: pyaggr3g470r/templates/home.html:58 +#: pyaggr3g470r/templates/home.html:64 msgid "Read" msgstr "Lus" -#: pyaggr3g470r/templates/home.html:59 pyaggr3g470r/templates/layout.html:115 +#: pyaggr3g470r/templates/home.html:65 pyaggr3g470r/templates/layout.html:106 msgid "Unread" msgstr "Non lus" -#: pyaggr3g470r/templates/home.html:76 +#: pyaggr3g470r/templates/home.html:81 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:622 +msgid "Feed" +msgstr "Flux" + +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:333 +msgid "Article" +msgstr "Article" + +#: pyaggr3g470r/templates/home.html:83 msgid "Date" msgstr "Date" @@ -644,39 +493,43 @@ msgstr "jours" msgid "No inactive feeds." msgstr "Aucun flux inactifs." -#: pyaggr3g470r/templates/layout.html:106 +#: pyaggr3g470r/templates/layout.html:97 msgid "Fetch" msgstr "Télécharger" -#: pyaggr3g470r/templates/layout.html:107 +#: pyaggr3g470r/templates/layout.html:98 msgid "Mark all as read" msgstr "Marquer tout comme lu" -#: pyaggr3g470r/templates/layout.html:113 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:609 +msgid "Add a feed" +msgstr "Ajouter un flux" + +#: pyaggr3g470r/templates/layout.html:104 msgid "Filter" msgstr "Filtrer" -#: pyaggr3g470r/templates/layout.html:116 +#: pyaggr3g470r/templates/layout.html:107 msgid "Favorites" msgstr "Favoris" -#: pyaggr3g470r/templates/layout.html:117 +#: pyaggr3g470r/templates/layout.html:108 msgid "Inactive feeds" msgstr "Flux inactifs" -#: pyaggr3g470r/templates/layout.html:119 +#: pyaggr3g470r/templates/layout.html:110 msgid "History" msgstr "Historique" -#: pyaggr3g470r/templates/layout.html:122 +#: pyaggr3g470r/templates/layout.html:113 msgid "Management" msgstr "Gestion" -#: pyaggr3g470r/templates/layout.html:124 +#: pyaggr3g470r/templates/layout.html:115 msgid "Dashboard" msgstr "Tableau de bord" -#: pyaggr3g470r/templates/layout.html:127 +#: pyaggr3g470r/templates/layout.html:118 msgid "Logout" msgstr "Déconnexion" @@ -828,6 +681,11 @@ msgstr "Supprimer cet utilisateur" msgid "You are going to delete this account." msgstr "Vous allez supprimer ce compte." +#: pyaggr3g470r/templates/admin/dashboard.html:45 +#: pyaggr3g470r/views/views.py:789 +msgid "Add a new user" +msgstr "Ajouter un nouvel utilisateur" + #: pyaggr3g470r/templates/admin/dashboard.html:46 msgid "Send notification messages" msgstr "Envoyer des messages de notification" @@ -852,6 +710,184 @@ msgstr "Nom de famille" msgid "Number of articles" msgstr "Nombre d'articles" +#: pyaggr3g470r/views/views.py:104 +msgid "Authentication required." +msgstr "Authentification requise." + +#: pyaggr3g470r/views/views.py:109 +msgid "Forbidden." +msgstr "Interdit." + +#: pyaggr3g470r/views/views.py:162 +msgid "Logged in successfully." +msgstr "Connecté avec succès." + +#: pyaggr3g470r/views/views.py:185 +msgid "Logged out successfully." +msgstr "Déconnecté avec succès." + +#: pyaggr3g470r/views/views.py:194 +msgid "Self-registration is disabled." +msgstr "L'auto-enregistrement est désactivé." + +#: pyaggr3g470r/views/views.py:211 +msgid "Email already used." +msgstr "Email déjà utilisé." + +#: pyaggr3g470r/views/views.py:218 pyaggr3g470r/views/views.py:840 +msgid "Problem while sending activation email" +msgstr "Problème lors de l'envoi d'email d'activation" + +#: pyaggr3g470r/views/views.py:221 +msgid "Your account has been created. Check your mail to confirm it." +msgstr "Votre compte a été créé. Vérifiez votre courrier pour le confirmer." + +#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:516 +msgid "Downloading articles..." +msgstr "Téléchargement des articles." + +#: pyaggr3g470r/views/views.py:333 +msgid "deleted." +msgstr "supprimé." + +#: pyaggr3g470r/views/views.py:336 +msgid "This article do not exist." +msgstr "Cet article n'existe pas." + +#: pyaggr3g470r/views/views.py:414 +msgid "Indexing database..." +msgstr "Indexation la base de données..." + +#: pyaggr3g470r/views/views.py:416 pyaggr3g470r/views/views.py:485 +msgid "An error occured" +msgstr "Une erreur est survenue." + +#: pyaggr3g470r/views/views.py:419 +msgid "Option not available on Heroku." +msgstr "Option non disponible sur Heroku." + +#: pyaggr3g470r/views/views.py:434 pyaggr3g470r/views/views.py:444 +msgid "Error when exporting articles." +msgstr "Erreur lors de l'export des articles." + +#: pyaggr3g470r/views/views.py:450 +msgid "Export format not supported." +msgstr "Ce format d'export n'est pas supporté." + +#: pyaggr3g470r/views/views.py:473 +msgid "Full text search is not yet implemented for Heroku." +msgstr "La recherche rapide n'est pas supporté sur Heroku." + +#: pyaggr3g470r/views/views.py:510 pyaggr3g470r/views/views.py:523 +#: pyaggr3g470r/views/views.py:531 +msgid "File not allowed." +msgstr "Fichier non autorisé." + +#: pyaggr3g470r/views/views.py:515 +msgid "feeds imported." +msgstr "flux importés." + +#: pyaggr3g470r/views/views.py:518 +msgid "Impossible to import the new feeds." +msgstr "Impossible d'importer les nouveaux flux." + +#: pyaggr3g470r/views/views.py:527 +msgid "Account imported." +msgstr "Compte importé." + +#: pyaggr3g470r/views/views.py:529 +msgid "Impossible to import the account." +msgstr "Impossible d'importer le compte." + +#: pyaggr3g470r/views/views.py:571 +msgid "Feed successfully updated." +msgstr "Flux mis à jour avec succès." + +#: pyaggr3g470r/views/views.py:582 +msgid "Feed successfully created." +msgstr "Flux créé avec succès." + +#: pyaggr3g470r/views/views.py:585 +msgid "Downloading articles for the new feed..." +msgstr "Téléchargement des articles du nouveau flux..." + +#: pyaggr3g470r/views/views.py:589 +msgid "Feed already in the database." +msgstr "Flux déjà dans la base de données." + +#: pyaggr3g470r/views/views.py:596 +msgid "Edit the feed" +msgstr "Éditez ce flux" + +#: pyaggr3g470r/views/views.py:622 pyaggr3g470r/views/views.py:817 +msgid "successfully deleted." +msgstr "supprimé avec succès." + +#: pyaggr3g470r/views/views.py:640 pyaggr3g470r/views/views.py:767 +#: pyaggr3g470r/views/views.py:777 pyaggr3g470r/views/views.py:817 +msgid "User" +msgstr "Utilisateur" + +#: pyaggr3g470r/views/views.py:641 pyaggr3g470r/views/views.py:767 +msgid "successfully updated." +msgstr "mis à jour avec succès." + +#: pyaggr3g470r/views/views.py:661 +msgid "Your account has been deleted." +msgstr "Votre compte a été supprimé." + +#: pyaggr3g470r/views/views.py:663 pyaggr3g470r/views/views.py:803 +#: pyaggr3g470r/views/views.py:819 pyaggr3g470r/views/views.py:847 +msgid "This user does not exist." +msgstr "Cet utilisateur n'existe pas." + +#: pyaggr3g470r/views/views.py:677 +msgid "Articles deleted." +msgstr "Articles supprimés." + +#: pyaggr3g470r/views/views.py:691 +msgid "Your account has been confirmed." +msgstr "Votre compte a été confirmé." + +#: pyaggr3g470r/views/views.py:693 +msgid "Impossible to confirm this account." +msgstr "Impossible de confirmer ce compte." + +#: pyaggr3g470r/views/views.py:715 +msgid "New password sent to your address." +msgstr "Nouveau mot de passe envoyé à votre adresse." + +#: pyaggr3g470r/views/views.py:717 +msgid "Problem while sending your new password." +msgstr "Problème lors de l'envoi de votre nouveau mot de passe." + +#: pyaggr3g470r/views/views.py:742 +msgid "Problem while sending email" +msgstr "Problème lors de l'envoi de l'email" + +#: pyaggr3g470r/views/views.py:777 +msgid "successfully created." +msgstr "créé avec succès." + +#: pyaggr3g470r/views/views.py:786 +msgid "Edit the user" +msgstr "Éditer cet utilisateur" + +#: pyaggr3g470r/views/views.py:838 pyaggr3g470r/views/views.py:844 +msgid "Account of the user" +msgstr "Compte de l'utilisateur" + +#: pyaggr3g470r/views/views.py:838 +msgid "successfully activated." +msgstr "activé avec succès." + +#: pyaggr3g470r/views/views.py:844 +msgid "successfully disabled." +msgstr "désactivé avec succès." + +#~ msgid "Email notification" +#~ msgstr "Notification par email" + #~ msgid "Database indexed." #~ msgstr "Base de données indexée." @@ -912,9 +948,6 @@ msgstr "Nombre d'articles" #~ msgid "First name" #~ msgstr "Prénom" -#~ msgid "Last name" -#~ msgstr "Nom de famille" - #~ msgid "Please enter your last name." #~ msgstr "S'il vous plaît, entrez votre nom de famille." -- cgit From c217114639e3a5d60de287462413615839a3e159 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 8 Mar 2015 17:50:10 +0100 Subject: Updated NEWS.rst for the release 6.3. --- NEWS.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 730a3dec..f4ca9cb0 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,5 +1,13 @@ pyAggr3g470r project news +6.3: 2015-03-08 + New: + * a new architecture with base for controllers; + * new, more complete RESTful API; + * a crawler handling errors and cache control; + * the new crawler takes advantage of the RESTful API + (can be run on the client side). + 6.2: 2015-02-26 The system of email notifications for new articles has been removed. This feature was hardly used. -- cgit From c625360db0971d1e79b5e56ad6e6d13cbbe7a927 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 9 Mar 2015 13:18:23 +0100 Subject: Test --- pyaggr3g470r/views/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 9d368c42..cb984a9c 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -574,11 +574,15 @@ def edit_feed(feed_id=None): # Create a new feed existing_feed = [f for f in g.user.feeds if f.link == form.link.data] if len(existing_feed) == 0: + print("Test 1") new_feed = Feed(title=form.title.data, description="", link=form.link.data, \ site_link=form.site_link.data, enabled=form.enabled.data) + print("Test 2") g.user.feeds.append(new_feed) #user.feeds = sorted(user.feeds, key=lambda t: t.title.lower()) + print("Test 3") db.session.commit() + print("Test 4") flash(gettext('Feed successfully created.'), 'success') utils.fetch(g.user.id, Feed.query.filter(Feed.link == form.link.data).first().id) -- cgit From be6398ccfe9c57d0642a0ac8eb62dcae2b7b5d23 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 9 Mar 2015 13:30:42 +0100 Subject: Test --- pyaggr3g470r/views/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index cb984a9c..579d1e1b 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -581,7 +581,10 @@ def edit_feed(feed_id=None): g.user.feeds.append(new_feed) #user.feeds = sorted(user.feeds, key=lambda t: t.title.lower()) print("Test 3") - db.session.commit() + try: + db.session.commit() + except Ecxeption as e: + print(e) print("Test 4") flash(gettext('Feed successfully created.'), 'success') -- cgit From 7a3c694e4b62ea73df023fe8a675896bd70ce1e5 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 9 Mar 2015 13:35:33 +0100 Subject: Bug fix. --- pyaggr3g470r/models/feed.py | 2 +- pyaggr3g470r/views/views.py | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/pyaggr3g470r/models/feed.py b/pyaggr3g470r/models/feed.py index 24542c28..9002aec3 100644 --- a/pyaggr3g470r/models/feed.py +++ b/pyaggr3g470r/models/feed.py @@ -47,7 +47,7 @@ class Feed(db.Model): # cache handling etag = db.Column(db.String(), default="") - last_modified = db.Column(db.String(), default="") + last_modified = db.Column(db.DateTime(), default=datetime.now) last_retrieved = db.Column(db.DateTime(), default=datetime(1970, 1, 1)) # error logging diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 579d1e1b..9d368c42 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -574,18 +574,11 @@ def edit_feed(feed_id=None): # Create a new feed existing_feed = [f for f in g.user.feeds if f.link == form.link.data] if len(existing_feed) == 0: - print("Test 1") new_feed = Feed(title=form.title.data, description="", link=form.link.data, \ site_link=form.site_link.data, enabled=form.enabled.data) - print("Test 2") g.user.feeds.append(new_feed) #user.feeds = sorted(user.feeds, key=lambda t: t.title.lower()) - print("Test 3") - try: - db.session.commit() - except Ecxeption as e: - print(e) - print("Test 4") + db.session.commit() flash(gettext('Feed successfully created.'), 'success') utils.fetch(g.user.id, Feed.query.filter(Feed.link == form.link.data).first().id) -- cgit From 427525eda2c227e4b25c11db9fd4f38f9efac54e Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 9 Mar 2015 13:36:35 +0100 Subject: Typo.* --- pyaggr3g470r/models/feed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/models/feed.py b/pyaggr3g470r/models/feed.py index 9002aec3..c80f302c 100644 --- a/pyaggr3g470r/models/feed.py +++ b/pyaggr3g470r/models/feed.py @@ -35,7 +35,7 @@ db = g.db class Feed(db.Model): """ - Represent a station. + Represent a feed. """ id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(), default="No title") -- cgit From b33684666e15e86840383cf8725df460a49e7deb Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 9 Mar 2015 13:46:21 +0100 Subject: Bug fix. --- pyaggr3g470r/static/js/articles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/static/js/articles.js b/pyaggr3g470r/static/js/articles.js index 312a5cb6..e30c6979 100644 --- a/pyaggr3g470r/static/js/articles.js +++ b/pyaggr3g470r/static/js/articles.js @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -API_ROOT = 'api/v2.0/' +API_ROOT = '/api/v2.0/' if (typeof jQuery === 'undefined') { throw new Error('Requires jQuery') } -- cgit From 6217315aae1392bc6c2e1881ba8e763def40969a Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 10 Mar 2015 14:28:47 +0100 Subject: changed the type of the column 'last_modified' to string. --- ...b75f3fe_changed_the_type_of_the_column_last_.py | 29 ++++++++++++++++++++++ pyaggr3g470r/models/feed.py | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py diff --git a/migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py b/migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py new file mode 100644 index 00000000..e7790b3f --- /dev/null +++ b/migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py @@ -0,0 +1,29 @@ +"""changed the type of the column 'last_modified' to string. + +Revision ID: 17dcb75f3fe +Revises: cde34831ea +Create Date: 2015-03-10 14:20:53.676344 + +""" + +# revision identifiers, used by Alembic. +revision = '17dcb75f3fe' +down_revision = 'cde34831ea' + +from alembic import op +import sqlalchemy as sa + +from datetime import datetime + +def upgrade(): + unix_start = datetime(1970, 1, 1) + op.drop_column('feed', 'last_modified') + op.add_column('feed', sa.Column('last_modified', sa.String(), + nullable=True, default=unix_start, server_default=str(unix_start))) + + +def downgrade(): + unix_start = datetime(1970, 1, 1) + op.drop_column('feed', 'last_modified') + op.add_column('feed', sa.Column('last_modified', sa.DateTime(), + nullable=True, default=unix_start, server_default=unix_start)) diff --git a/pyaggr3g470r/models/feed.py b/pyaggr3g470r/models/feed.py index c80f302c..ccc8094f 100644 --- a/pyaggr3g470r/models/feed.py +++ b/pyaggr3g470r/models/feed.py @@ -47,7 +47,7 @@ class Feed(db.Model): # cache handling etag = db.Column(db.String(), default="") - last_modified = db.Column(db.DateTime(), default=datetime.now) + last_modified = db.Column(db.String(), default="") last_retrieved = db.Column(db.DateTime(), default=datetime(1970, 1, 1)) # error logging -- cgit From 0dd06d8e6047be57295d5346857fb62fc1c103b5 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 10 Mar 2015 22:13:46 +0100 Subject: The label of the badge (for the errors count) wasn't clear enough. --- messages.pot | 6 +++++- pyaggr3g470r/templates/home.html | 4 ++-- .../translations/fr/LC_MESSAGES/messages.mo | Bin 15220 -> 15249 bytes .../translations/fr/LC_MESSAGES/messages.po | 8 ++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/messages.pot b/messages.pot index 2db4ff68..95d9b66b 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-08 17:28+0100\n" +"POT-Creation-Date: 2015-03-10 22:10+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -420,6 +420,10 @@ msgstr "" msgid "All feeds" msgstr "" +#: pyaggr3g470r/templates/home.html:25 pyaggr3g470r/templates/home.html:43 +msgid "error" +msgstr "" + #: pyaggr3g470r/templates/home.html:36 pyaggr3g470r/templates/home.html:54 msgid "Mark this feed as read" msgstr "" diff --git a/pyaggr3g470r/templates/home.html b/pyaggr3g470r/templates/home.html index 3a9608d5..f2d2218b 100644 --- a/pyaggr3g470r/templates/home.html +++ b/pyaggr3g470r/templates/home.html @@ -22,7 +22,7 @@
  • {% if feed_id == fid %}{% endif %} {% if in_error.get(fid, 0) > 0 %} - 2 else "orange" }} ;" class="badge pull-right" title="Some errors occured while trying to retrieve that feed.">{{ in_error[fid] }} + 2 else "orange" }} ;" class="badge pull-right" title="Some errors occured while trying to retrieve that feed.">{{ in_error[fid] }} {{ _("error") }}{% if in_error[fid] > 1 %}s{% endif %} {% endif %} {{ nbunread }} {{ feeds[fid]|safe }} @@ -40,7 +40,7 @@ {% for fid, ftitle in feeds|dictsort(case_sensitive=False, by='value') if not fid in unread %}
  • {% if in_error.get(fid, 0) > 0 %} - 2 else "orange" }} ;" class="badge pull-right" title="Some errors occured while trying to retrieve that feed.">{{ in_error[fid] }} + 2 else "orange" }} ;" class="badge pull-right" title="Some errors occured while trying to retrieve that feed.">{{ in_error[fid] }} {{ _("error") }}{% if in_error[fid] > 1 %}s{% endif %} {% endif %} {% if feed_id == fid %}{% endif %} {{ ftitle|safe }} diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index 5ac1b770..00bbb6e1 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index 81af46ed..df32599d 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-08 17:28+0100\n" -"PO-Revision-Date: 2015-03-08 17:34+0100\n" +"POT-Creation-Date: 2015-03-10 22:10+0100\n" +"PO-Revision-Date: 2015-03-10 22:11+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -448,6 +448,10 @@ msgstr "téléchargez un fichier OPML." msgid "All feeds" msgstr "Tous les flux" +#: pyaggr3g470r/templates/home.html:25 pyaggr3g470r/templates/home.html:43 +msgid "error" +msgstr "erreur" + #: pyaggr3g470r/templates/home.html:36 pyaggr3g470r/templates/home.html:54 msgid "Mark this feed as read" msgstr "Marquer ce flux comme lu" -- cgit From 9f6ba4d43d4c53205b0fa2ab1521abc67054ed53 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 12 Mar 2015 08:13:32 +0100 Subject: Default platform URL should be localhost (especially if the user don't use the Heroku instance). --- conf/conf.cfg-sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/conf.cfg-sample b/conf/conf.cfg-sample index 4f1e06c6..e5b2683b 100644 --- a/conf/conf.cfg-sample +++ b/conf/conf.cfg-sample @@ -1,5 +1,5 @@ [misc] -platform_url = https://pyaggr3g470r.herokuapp.com/ +platform_url = http://127.0.0.1:5000/ admin_email = recaptcha_public_key = recaptcha_private_key = -- cgit From 4f35da2ce8c38474854736a4cff47fa5407ebe5d Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 12 Mar 2015 08:26:01 +0100 Subject: Updated documentation. --- documentation/deployment.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 8a7f098d..64fd1d30 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -131,16 +131,17 @@ Finally: Configuration ============= -Configuration (database url, email, proxy, user agent, etc.) is done via the file *conf/conf.cfg*. -Check these configuration before executing *db_create.py*. +Configuration (database url, email, proxy, user agent, etc.) is done via the file `conf/conf.cfg`. +Check this file before initializing the database (with `manager.py`). + If you want to use pyAggr3g470r with Tor/Privoxy, you just have to set the value of -*http_proxy* (most of the time: *http_proxy = 127.0.0.1:8118**). Else leave the value blank. +`http_proxy` (most of the time: `http_proxy = 127.0.0.1:8118`). Else leave the value blank. Automatic updates ================= -You can fetch new articles with `cron `_ and the script *fetch.py*. +You can fetch new articles with `cron `_. For example if you want to check for updates every 30 minutes, add this line to your cron rules (*crontab -e*): .. code-block:: bash -- cgit From 28475f1b6f8dcfde8b65d5643684ad4c2437c7fb Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 15 Mar 2015 16:32:33 +0100 Subject: psycopg2 is now in the requirements.txt file. --- documentation/deployment.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 64fd1d30..9cae0ddf 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -92,7 +92,6 @@ If you want to use PostgreSQL .. code-block:: bash $ sudo apt-get install postgresql postgresql-server-dev-9.3 postgresql-client - $ pip install psycopg2 $ echo "127.0.0.1:5432:aggregator:pgsqluser:pgsqlpwd" > ~/.pgpass $ chmod 700 ~/.pgpass $ sudo -u postgres createuser pgsqluser --no-superuser --createdb --no-createrole -- cgit From 9dbcb517cdf73c2e476d8ef9ddba0d84f2e3023b Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 15 Mar 2015 16:34:41 +0100 Subject: Minor changes to the documentation. --- documentation/deployment.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 9cae0ddf..3aedbb60 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -3,7 +3,8 @@ Deployment This application can be deployed on Heroku or on a traditional server. -After installation, you will be able to connect with the email *root@pyAggr3g470r.localhost* and the password *password*. +After installation, you will be able to connect with the email +*root@pyAggr3g470r.localhost* and the password *password*. Deploying the application with Vagrant -------------------------------------- @@ -45,7 +46,8 @@ The geek way $ heroku run init $ heroku ps:scale web=1 -To enable account creation for users, you have to set some environment variables: +To enable account creation for users, you have to set some environment +variables: .. code-block:: bash @@ -130,21 +132,22 @@ Finally: Configuration ============= -Configuration (database url, email, proxy, user agent, etc.) is done via the file `conf/conf.cfg`. +Configuration (database url, email, proxy, user agent, etc.) is done via the +file `conf/conf.cfg`. Check this file before initializing the database (with `manager.py`). -If you want to use pyAggr3g470r with Tor/Privoxy, you just have to set the value of -`http_proxy` (most of the time: `http_proxy = 127.0.0.1:8118`). Else leave the value blank. +If you want to use pyAggr3g470r with Tor/Privoxy, you just have to set the value +of `http_proxy` (most of the time: `http_proxy = 127.0.0.1:8118`). Else leave +the value blank. Automatic updates ================= You can fetch new articles with `cron `_. -For example if you want to check for updates every 30 minutes, add this line to your cron rules (*crontab -e*): +For example if you want to check for updates every 30 minutes, add this line to +your cron rules (*crontab -e*): .. code-block:: bash */30 * * * * cd ~/.pyaggr3g470r/ ; python manager.py fetch_asyncio None None - -You must give the email address you use to login to pyAggr3g470r. -- cgit From 9a1a50f7cb2f63071fe127a29fece79585ea4037 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 15 Mar 2015 17:20:38 +0100 Subject: pylint check --- pyaggr3g470r/controllers/abstract.py | 1 - pyaggr3g470r/controllers/feed.py | 6 +++--- pyaggr3g470r/notifications.py | 18 ++++++++++++------ pyaggr3g470r/views/api/common.py | 1 - pyaggr3g470r/views/views.py | 3 +-- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pyaggr3g470r/controllers/abstract.py b/pyaggr3g470r/controllers/abstract.py index a99e67f3..c084deb9 100644 --- a/pyaggr3g470r/controllers/abstract.py +++ b/pyaggr3g470r/controllers/abstract.py @@ -1,6 +1,5 @@ import logging from bootstrap import db -from sqlalchemy import update from werkzeug.exceptions import Forbidden, NotFound logger = logging.getLogger(__name__) diff --git a/pyaggr3g470r/controllers/feed.py b/pyaggr3g470r/controllers/feed.py index a3cdcddd..342ab88e 100644 --- a/pyaggr3g470r/controllers/feed.py +++ b/pyaggr3g470r/controllers/feed.py @@ -1,4 +1,4 @@ -from datetime import datetime, timedelta +from datetime import datetime from .abstract import AbstractController from pyaggr3g470r.models import Feed @@ -17,7 +17,7 @@ class FeedController(AbstractController): feeds = [feed for feed in self.read(user_id=self.user_id, error_count__lt=max_error, enabled=True).limit(limit)] #last_retrieved__lt=max_last).limit(limit)] - """if feeds: + if feeds: self.update({'id__in': [feed.id for feed in feeds]}, - {'last_retrieved': now})""" + {'last_retrieved': now}) return feeds diff --git a/pyaggr3g470r/notifications.py b/pyaggr3g470r/notifications.py index cf8fb723..006aa594 100644 --- a/pyaggr3g470r/notifications.py +++ b/pyaggr3g470r/notifications.py @@ -30,10 +30,12 @@ def information_message(subject, plaintext): from pyaggr3g470r.models import User users = User.query.all() # Only send email for activated accounts. - emails = [user.email for user in users if user.activation_key == ""] + user_emails = [user.email for user in users if user.activation_key == ""] # Postmark has a limit of twenty recipients per message in total. - for i in xrange(0, len(emails), 19): - emails.send(to=conf.NOTIFICATION_EMAIL, bcc=", ".join(emails[i:i+19]), subject=subject, plaintext=plaintext) + for i in xrange(0, len(user_emails), 19): + emails.send(to=conf.NOTIFICATION_EMAIL, + bcc=", ".join(user_emails[i:i+19]), + subject=subject, plaintext=plaintext) def new_account_notification(user): """ @@ -41,7 +43,8 @@ def new_account_notification(user): """ plaintext = """Hello,\n\nYour account has been created. Click on the following link to confirm it:\n%s\n\nSee you,""" % \ (conf.PLATFORM_URL + 'confirm_account/' + user.activation_key) - emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, subject="[pyAggr3g470r] Account creation", plaintext=plaintext) + emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, + subject="[pyAggr3g470r] Account creation", plaintext=plaintext) def new_account_activation(user): """ @@ -49,7 +52,8 @@ def new_account_activation(user): """ plaintext = """Hello,\n\nYour account has been activated. You can now connect to the platform:\n%s\n\nSee you,""" % \ (conf.PLATFORM_URL) - emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, subject="[pyAggr3g470r] Account activated", plaintext=plaintext) + emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, + subject="[pyAggr3g470r] Account activated", plaintext=plaintext) def new_password_notification(user, password): """ @@ -58,4 +62,6 @@ def new_password_notification(user, password): plaintext = """Hello,\n\nA new password has been generated at your request:\n\n%s""" % \ (password, ) plaintext += "\n\nIt is advised to replace it as soon as connected to pyAggr3g470r.\n\nSee you," - emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, subject="[pyAggr3g470r] New password", plaintext=plaintext) + emails.send(to=user.email, + bcc=conf.NOTIFICATION_EMAIL, + subject="[pyAggr3g470r] New password", plaintext=plaintext) diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index 856b4bb9..b1b0cd73 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -24,7 +24,6 @@ routes : import json import logging import dateutil.parser -from copy import deepcopy from functools import wraps from werkzeug.exceptions import Unauthorized, BadRequest from flask import request, g, session, Response diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 9d368c42..88835068 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -27,14 +27,13 @@ __copyright__ = "Copyright (c) Cedric Bonhomme" __license__ = "AGPLv3" import os -import json import string import random import hashlib import datetime from collections import namedtuple from bootstrap import application as app, db -from flask import render_template, request, flash, session, Response, \ +from flask import render_template, request, flash, session, \ url_for, redirect, g, current_app, make_response, jsonify from flask.ext.login import LoginManager, login_user, logout_user, \ login_required, current_user, AnonymousUserMixin -- cgit From fb5df6041fc7bf97429bfe689e26fdc08e7e307f Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 15 Mar 2015 23:59:14 +0100 Subject: A new test for the history page. --- pyaggr3g470r/templates/history.html | 89 +++++++------------------------------ pyaggr3g470r/utils.py | 26 +++++++++++ pyaggr3g470r/views/views.py | 11 +++-- 3 files changed, 50 insertions(+), 76 deletions(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index 0194cb89..6216f616 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -1,74 +1,19 @@ - {% extends "layout.html" %} - {% block head %} -{{ super() }} - - -{% endblock %} - +{% extends "layout.html" %} {% block content %} +{% endblock %} diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index ba440c78..ae140327 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -54,6 +54,7 @@ from contextlib import contextmanager import conf from flask import g +from pyaggr3g470r import controllers from pyaggr3g470r.models import User, Feed, Article @@ -84,6 +85,31 @@ def fetch(id, feed_id=None): cmd = [conf.PYTHON, conf.basedir+'/manager.py', 'fetch_asyncio', str(id), str(feed_id)] p = subprocess.Popen(cmd, stdout=subprocess.PIPE) +def history(year=None, month=None): + """ + """ + import datetime, time, sqlalchemy + articles_counter = Counter() + if None != month and None != year: + articles = controllers.ArticleController(1).read(). \ + filter(sqlalchemy.extract('year', Article.date) == year). \ + filter(sqlalchemy.extract('month', Article.date) == month) + elif None != year: + articles = controllers.ArticleController(1).read(). \ + filter(sqlalchemy.extract('year', Article.date) == year) + else: + articles = controllers.ArticleController(1).read() + + for article in articles: + if None != month: + articles_counter[article.date.day] += 1 + elif None != year: + articles_counter[article.date.month] += 1 + else: + articles_counter[article.date.year] += 1 + + return articles_counter, articles + def import_opml(email, opml_content): """ Import new feeds from an OPML file. diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 88835068..b7ccf955 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -539,10 +539,13 @@ def management(): not_on_heroku = not conf.ON_HEROKU) @app.route('/history', methods=['GET']) -@login_required -def history(): - #user = User.query.filter(User.id == g.user.id).first() - return render_template('history.html') +@app.route('/history/', methods=['GET']) +@app.route('/history//', methods=['GET']) +def history(year=None, month=None): + articles_counter, articles = utils.history(year, month) + return render_template('history.html', articles_counter=articles_counter, + articles=articles, + year=year, month=month) @app.route('/bookmarklet', methods=['GET']) @app.route('/create_feed', methods=['GET', 'POST']) -- cgit From 17bf200599ec978d8833a22aac85a803395d5207 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 15 Mar 2015 23:59:56 +0100 Subject: forgot login required decorator --- pyaggr3g470r/views/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index b7ccf955..c6f0d3d0 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -541,6 +541,7 @@ def management(): @app.route('/history', methods=['GET']) @app.route('/history/', methods=['GET']) @app.route('/history//', methods=['GET']) +@login_required def history(year=None, month=None): articles_counter, articles = utils.history(year, month) return render_template('history.html', articles_counter=articles_counter, -- cgit From 8d0fea82761f2fdc1ea93687429990eefa851fc8 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 16 Mar 2015 07:22:52 +0100 Subject: Improvements and fixes for the history() function. --- pyaggr3g470r/templates/history.html | 2 +- pyaggr3g470r/utils.py | 24 +++++++++--------------- pyaggr3g470r/views/views.py | 9 +++++---- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index 6216f616..2d64da98 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -10,7 +10,7 @@
  • {{ article }} : {{ articles_counter[article] }} articles
  • {% else %} {% for article in articles %} -
  • {{ article.title | safe }}
  • +
  • {{ article.date }} - {{ article.title | safe }}
  • {% endfor %} {% endif %} {% endfor %} diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index ae140327..1ad2896a 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -43,6 +43,7 @@ import operator import urllib import itertools import subprocess +import sqlalchemy try: from urlparse import urlparse, parse_qs, urlunparse except: @@ -85,25 +86,18 @@ def fetch(id, feed_id=None): cmd = [conf.PYTHON, conf.basedir+'/manager.py', 'fetch_asyncio', str(id), str(feed_id)] p = subprocess.Popen(cmd, stdout=subprocess.PIPE) -def history(year=None, month=None): +def history(user_id, year=None, month=None): """ """ - import datetime, time, sqlalchemy articles_counter = Counter() - if None != month and None != year: - articles = controllers.ArticleController(1).read(). \ - filter(sqlalchemy.extract('year', Article.date) == year). \ - filter(sqlalchemy.extract('month', Article.date) == month) - elif None != year: - articles = controllers.ArticleController(1).read(). \ - filter(sqlalchemy.extract('year', Article.date) == year) - else: - articles = controllers.ArticleController(1).read() - - for article in articles: + articles = controllers.ArticleController(user_id).read() + if None != year: + articles = articles.filter(sqlalchemy.extract('year', Article.date) == year) if None != month: - articles_counter[article.date.day] += 1 - elif None != year: + articles = articles.filter(sqlalchemy.extract('month', Article.date) == month) + print(articles.count()) + for article in articles.all(): + if None != year: articles_counter[article.date.month] += 1 else: articles_counter[article.date.year] += 1 diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index c6f0d3d0..9aefd6b1 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -543,10 +543,11 @@ def management(): @app.route('/history//', methods=['GET']) @login_required def history(year=None, month=None): - articles_counter, articles = utils.history(year, month) - return render_template('history.html', articles_counter=articles_counter, - articles=articles, - year=year, month=month) + articles_counter, articles = utils.history(g.user.id, year, month) + return render_template('history.html', + articles_counter=articles_counter, + articles=articles, + year=year, month=month) @app.route('/bookmarklet', methods=['GET']) @app.route('/create_feed', methods=['GET', 'POST']) -- cgit From 052dd984ee98adf75c9ad022f6f2d6cc9cc88b36 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 16 Mar 2015 07:24:24 +0100 Subject: Removed debug print. --- pyaggr3g470r/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index 1ad2896a..b1c9ff50 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -95,7 +95,6 @@ def history(user_id, year=None, month=None): articles = articles.filter(sqlalchemy.extract('year', Article.date) == year) if None != month: articles = articles.filter(sqlalchemy.extract('month', Article.date) == month) - print(articles.count()) for article in articles.all(): if None != year: articles_counter[article.date.month] += 1 -- cgit From aaa6013c0e8a477378fb5de9f3362ae17d933788 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 16 Mar 2015 07:25:01 +0100 Subject: Removed blank line. --- pyaggr3g470r/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index b1c9ff50..e88f5261 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -100,7 +100,6 @@ def history(user_id, year=None, month=None): articles_counter[article.date.month] += 1 else: articles_counter[article.date.year] += 1 - return articles_counter, articles def import_opml(email, opml_content): -- cgit From f322fba75c8ca3dd4296a11bda688d63b2a547d2 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 16 Mar 2015 07:36:11 +0100 Subject: Added a new Jinja filter to get month name from number. --- pyaggr3g470r/templates/history.html | 2 +- runserver.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index 2d64da98..3b9412a3 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -7,7 +7,7 @@ {% if year == None %}
  • {{ article }} : {{ articles_counter[article] }} articles
  • {% elif month == None %} -
  • {{ article }} : {{ articles_counter[article] }} articles
  • +
  • {{ article | month_name }} : {{ articles_counter[article] }} articles
  • {% else %} {% for article in articles %}
  • {{ article.date }} - {{ article.title | safe }}
  • diff --git a/runserver.py b/runserver.py index 2ced409f..156ae320 100755 --- a/runserver.py +++ b/runserver.py @@ -18,7 +18,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +import calendar from bootstrap import conf, application, db, populate_g from flask.ext.babel import Babel from flask.ext.babel import format_datetime @@ -38,8 +38,14 @@ def allowed_file(filename): babel = Babel(application) +# Jinja filters application.jinja_env.filters['datetime'] = format_datetime +#@register.filter +def month_name(month_number): + return calendar.month_name[month_number] +application.jinja_env.filters['month_name'] = month_name + # Views from flask.ext.restful import Api from flask import g -- cgit From 3cb61e31e6642cba163604893efcca98b46f4b68 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 16 Mar 2015 13:30:02 +0100 Subject: Improvements to the 'history' page. --- pyaggr3g470r/templates/history.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index 3b9412a3..c4d6c9a6 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -2,6 +2,13 @@ {% block content %}

    {{ _('History') }}

    + {% if month != None %} +

    {{ year }}

    +

    {{ month | month_name }}

    + {% elif year != None %} +

     {{ _('all years') }}

    +

    {{ year }}

    + {% endif %}
      {% for article in articles_counter %} {% if year == None %} @@ -9,7 +16,7 @@ {% elif month == None %}
    • {{ article | month_name }} : {{ articles_counter[article] }} articles
    • {% else %} - {% for article in articles %} + {% for article in articles | sort(attribute="date") %}
    • {{ article.date }} - {{ article.title | safe }}
    • {% endfor %} {% endif %} -- cgit From 264c916b1e83a3f429c87a14d69c45e87a5afbd0 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 17 Mar 2015 06:56:38 +0100 Subject: Reverse the sort of articles. --- pyaggr3g470r/templates/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index c4d6c9a6..b01ca032 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -16,7 +16,7 @@ {% elif month == None %}
    • {{ article | month_name }} : {{ articles_counter[article] }} articles
    • {% else %} - {% for article in articles | sort(attribute="date") %} + {% for article in articles | sort(attribute="date", reverse = True) %}
    • {{ article.date }} - {{ article.title | safe }}
    • {% endfor %} {% endif %} -- cgit From a5d1461039ed8b1b1da17d353901c0a3c08fde26 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 17 Mar 2015 07:04:42 +0100 Subject: Updated NEWS.rst for the release 6.4. --- NEWS.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index f4ca9cb0..1e687bd8 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,5 +1,14 @@ pyAggr3g470r project news +6.4: 2015-03-17 + New: + * a new page 'history' to explore your database of articles. + Changes: + * updated documentation; + * minor improvements. + Fixes: + * changed the type of the column 'last_modified' to string. + 6.3: 2015-03-08 New: * a new architecture with base for controllers; -- cgit From 09715ee00be56af9503fddffda3d580717b8ce9a Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 17 Mar 2015 18:23:14 +0100 Subject: Updated translations. --- messages.pot | 114 ++++++++++---------- .../translations/fr/LC_MESSAGES/messages.mo | Bin 15249 -> 15318 bytes .../translations/fr/LC_MESSAGES/messages.po | 117 +++++++++++---------- 3 files changed, 120 insertions(+), 111 deletions(-) diff --git a/messages.pot b/messages.pot index 95d9b66b..e54e116e 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-10 22:10+0100\n" +"POT-Creation-Date: 2015-03-17 18:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -399,6 +399,14 @@ msgstr "" msgid "Duplicate articles" msgstr "" +#: pyaggr3g470r/templates/history.html:4 pyaggr3g470r/templates/layout.html:110 +msgid "History" +msgstr "" + +#: pyaggr3g470r/templates/history.html:9 +msgid "all years" +msgstr "" + #: pyaggr3g470r/templates/home.html:10 msgid "You don't have any feeds." msgstr "" @@ -445,11 +453,11 @@ msgid "Unread" msgstr "" #: pyaggr3g470r/templates/home.html:81 -#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:622 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:626 msgid "Feed" msgstr "" -#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:333 +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:332 msgid "Article" msgstr "" @@ -477,7 +485,7 @@ msgstr "" msgid "Mark all as read" msgstr "" -#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:609 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:613 msgid "Add a feed" msgstr "" @@ -493,10 +501,6 @@ msgstr "" msgid "Inactive feeds" msgstr "" -#: pyaggr3g470r/templates/layout.html:110 -msgid "History" -msgstr "" - #: pyaggr3g470r/templates/layout.html:113 msgid "Management" msgstr "" @@ -658,7 +662,7 @@ msgid "You are going to delete this account." msgstr "" #: pyaggr3g470r/templates/admin/dashboard.html:45 -#: pyaggr3g470r/views/views.py:789 +#: pyaggr3g470r/views/views.py:793 msgid "Add a new user" msgstr "" @@ -686,178 +690,178 @@ msgstr "" msgid "Number of articles" msgstr "" -#: pyaggr3g470r/views/views.py:104 +#: pyaggr3g470r/views/views.py:103 msgid "Authentication required." msgstr "" -#: pyaggr3g470r/views/views.py:109 +#: pyaggr3g470r/views/views.py:108 msgid "Forbidden." msgstr "" -#: pyaggr3g470r/views/views.py:162 +#: pyaggr3g470r/views/views.py:161 msgid "Logged in successfully." msgstr "" -#: pyaggr3g470r/views/views.py:185 +#: pyaggr3g470r/views/views.py:184 msgid "Logged out successfully." msgstr "" -#: pyaggr3g470r/views/views.py:194 +#: pyaggr3g470r/views/views.py:193 msgid "Self-registration is disabled." msgstr "" -#: pyaggr3g470r/views/views.py:211 +#: pyaggr3g470r/views/views.py:210 msgid "Email already used." msgstr "" -#: pyaggr3g470r/views/views.py:218 pyaggr3g470r/views/views.py:840 +#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:844 msgid "Problem while sending activation email" msgstr "" -#: pyaggr3g470r/views/views.py:221 +#: pyaggr3g470r/views/views.py:220 msgid "Your account has been created. Check your mail to confirm it." msgstr "" -#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:516 +#: pyaggr3g470r/views/views.py:268 pyaggr3g470r/views/views.py:515 msgid "Downloading articles..." msgstr "" -#: pyaggr3g470r/views/views.py:333 +#: pyaggr3g470r/views/views.py:332 msgid "deleted." msgstr "" -#: pyaggr3g470r/views/views.py:336 +#: pyaggr3g470r/views/views.py:335 msgid "This article do not exist." msgstr "" -#: pyaggr3g470r/views/views.py:414 +#: pyaggr3g470r/views/views.py:413 msgid "Indexing database..." msgstr "" -#: pyaggr3g470r/views/views.py:416 pyaggr3g470r/views/views.py:485 +#: pyaggr3g470r/views/views.py:415 pyaggr3g470r/views/views.py:484 msgid "An error occured" msgstr "" -#: pyaggr3g470r/views/views.py:419 +#: pyaggr3g470r/views/views.py:418 msgid "Option not available on Heroku." msgstr "" -#: pyaggr3g470r/views/views.py:434 pyaggr3g470r/views/views.py:444 +#: pyaggr3g470r/views/views.py:433 pyaggr3g470r/views/views.py:443 msgid "Error when exporting articles." msgstr "" -#: pyaggr3g470r/views/views.py:450 +#: pyaggr3g470r/views/views.py:449 msgid "Export format not supported." msgstr "" -#: pyaggr3g470r/views/views.py:473 +#: pyaggr3g470r/views/views.py:472 msgid "Full text search is not yet implemented for Heroku." msgstr "" -#: pyaggr3g470r/views/views.py:510 pyaggr3g470r/views/views.py:523 -#: pyaggr3g470r/views/views.py:531 +#: pyaggr3g470r/views/views.py:509 pyaggr3g470r/views/views.py:522 +#: pyaggr3g470r/views/views.py:530 msgid "File not allowed." msgstr "" -#: pyaggr3g470r/views/views.py:515 +#: pyaggr3g470r/views/views.py:514 msgid "feeds imported." msgstr "" -#: pyaggr3g470r/views/views.py:518 +#: pyaggr3g470r/views/views.py:517 msgid "Impossible to import the new feeds." msgstr "" -#: pyaggr3g470r/views/views.py:527 +#: pyaggr3g470r/views/views.py:526 msgid "Account imported." msgstr "" -#: pyaggr3g470r/views/views.py:529 +#: pyaggr3g470r/views/views.py:528 msgid "Impossible to import the account." msgstr "" -#: pyaggr3g470r/views/views.py:571 +#: pyaggr3g470r/views/views.py:575 msgid "Feed successfully updated." msgstr "" -#: pyaggr3g470r/views/views.py:582 +#: pyaggr3g470r/views/views.py:586 msgid "Feed successfully created." msgstr "" -#: pyaggr3g470r/views/views.py:585 +#: pyaggr3g470r/views/views.py:589 msgid "Downloading articles for the new feed..." msgstr "" -#: pyaggr3g470r/views/views.py:589 +#: pyaggr3g470r/views/views.py:593 msgid "Feed already in the database." msgstr "" -#: pyaggr3g470r/views/views.py:596 +#: pyaggr3g470r/views/views.py:600 msgid "Edit the feed" msgstr "" -#: pyaggr3g470r/views/views.py:622 pyaggr3g470r/views/views.py:817 +#: pyaggr3g470r/views/views.py:626 pyaggr3g470r/views/views.py:821 msgid "successfully deleted." msgstr "" -#: pyaggr3g470r/views/views.py:640 pyaggr3g470r/views/views.py:767 -#: pyaggr3g470r/views/views.py:777 pyaggr3g470r/views/views.py:817 +#: pyaggr3g470r/views/views.py:644 pyaggr3g470r/views/views.py:771 +#: pyaggr3g470r/views/views.py:781 pyaggr3g470r/views/views.py:821 msgid "User" msgstr "" -#: pyaggr3g470r/views/views.py:641 pyaggr3g470r/views/views.py:767 +#: pyaggr3g470r/views/views.py:645 pyaggr3g470r/views/views.py:771 msgid "successfully updated." msgstr "" -#: pyaggr3g470r/views/views.py:661 +#: pyaggr3g470r/views/views.py:665 msgid "Your account has been deleted." msgstr "" -#: pyaggr3g470r/views/views.py:663 pyaggr3g470r/views/views.py:803 -#: pyaggr3g470r/views/views.py:819 pyaggr3g470r/views/views.py:847 +#: pyaggr3g470r/views/views.py:667 pyaggr3g470r/views/views.py:807 +#: pyaggr3g470r/views/views.py:823 pyaggr3g470r/views/views.py:851 msgid "This user does not exist." msgstr "" -#: pyaggr3g470r/views/views.py:677 +#: pyaggr3g470r/views/views.py:681 msgid "Articles deleted." msgstr "" -#: pyaggr3g470r/views/views.py:691 +#: pyaggr3g470r/views/views.py:695 msgid "Your account has been confirmed." msgstr "" -#: pyaggr3g470r/views/views.py:693 +#: pyaggr3g470r/views/views.py:697 msgid "Impossible to confirm this account." msgstr "" -#: pyaggr3g470r/views/views.py:715 +#: pyaggr3g470r/views/views.py:719 msgid "New password sent to your address." msgstr "" -#: pyaggr3g470r/views/views.py:717 +#: pyaggr3g470r/views/views.py:721 msgid "Problem while sending your new password." msgstr "" -#: pyaggr3g470r/views/views.py:742 +#: pyaggr3g470r/views/views.py:746 msgid "Problem while sending email" msgstr "" -#: pyaggr3g470r/views/views.py:777 +#: pyaggr3g470r/views/views.py:781 msgid "successfully created." msgstr "" -#: pyaggr3g470r/views/views.py:786 +#: pyaggr3g470r/views/views.py:790 msgid "Edit the user" msgstr "" -#: pyaggr3g470r/views/views.py:838 pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:842 pyaggr3g470r/views/views.py:848 msgid "Account of the user" msgstr "" -#: pyaggr3g470r/views/views.py:838 +#: pyaggr3g470r/views/views.py:842 msgid "successfully activated." msgstr "" -#: pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:848 msgid "successfully disabled." msgstr "" diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index 00bbb6e1..8f232509 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index df32599d..fdf98b3b 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-10 22:10+0100\n" -"PO-Revision-Date: 2015-03-10 22:11+0100\n" +"POT-Creation-Date: 2015-03-17 18:22+0100\n" +"PO-Revision-Date: 2015-03-17 18:22+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -427,6 +427,15 @@ msgstr "Flux désactivé" msgid "Duplicate articles" msgstr "Articles doublon" +#: pyaggr3g470r/templates/history.html:4 +#: pyaggr3g470r/templates/layout.html:110 +msgid "History" +msgstr "Historique" + +#: pyaggr3g470r/templates/history.html:9 +msgid "all years" +msgstr "toutes les années" + #: pyaggr3g470r/templates/home.html:10 msgid "You don't have any feeds." msgstr "Vous n'avez pas de flux." @@ -473,11 +482,11 @@ msgid "Unread" msgstr "Non lus" #: pyaggr3g470r/templates/home.html:81 -#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:622 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:626 msgid "Feed" msgstr "Flux" -#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:333 +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:332 msgid "Article" msgstr "Article" @@ -505,7 +514,7 @@ msgstr "Télécharger" msgid "Mark all as read" msgstr "Marquer tout comme lu" -#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:609 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:613 msgid "Add a feed" msgstr "Ajouter un flux" @@ -521,10 +530,6 @@ msgstr "Favoris" msgid "Inactive feeds" msgstr "Flux inactifs" -#: pyaggr3g470r/templates/layout.html:110 -msgid "History" -msgstr "Historique" - #: pyaggr3g470r/templates/layout.html:113 msgid "Management" msgstr "Gestion" @@ -686,7 +691,7 @@ msgid "You are going to delete this account." msgstr "Vous allez supprimer ce compte." #: pyaggr3g470r/templates/admin/dashboard.html:45 -#: pyaggr3g470r/views/views.py:789 +#: pyaggr3g470r/views/views.py:793 msgid "Add a new user" msgstr "Ajouter un nouvel utilisateur" @@ -714,178 +719,178 @@ msgstr "Nom de famille" msgid "Number of articles" msgstr "Nombre d'articles" -#: pyaggr3g470r/views/views.py:104 +#: pyaggr3g470r/views/views.py:103 msgid "Authentication required." msgstr "Authentification requise." -#: pyaggr3g470r/views/views.py:109 +#: pyaggr3g470r/views/views.py:108 msgid "Forbidden." msgstr "Interdit." -#: pyaggr3g470r/views/views.py:162 +#: pyaggr3g470r/views/views.py:161 msgid "Logged in successfully." msgstr "Connecté avec succès." -#: pyaggr3g470r/views/views.py:185 +#: pyaggr3g470r/views/views.py:184 msgid "Logged out successfully." msgstr "Déconnecté avec succès." -#: pyaggr3g470r/views/views.py:194 +#: pyaggr3g470r/views/views.py:193 msgid "Self-registration is disabled." msgstr "L'auto-enregistrement est désactivé." -#: pyaggr3g470r/views/views.py:211 +#: pyaggr3g470r/views/views.py:210 msgid "Email already used." msgstr "Email déjà utilisé." -#: pyaggr3g470r/views/views.py:218 pyaggr3g470r/views/views.py:840 +#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:844 msgid "Problem while sending activation email" msgstr "Problème lors de l'envoi d'email d'activation" -#: pyaggr3g470r/views/views.py:221 +#: pyaggr3g470r/views/views.py:220 msgid "Your account has been created. Check your mail to confirm it." msgstr "Votre compte a été créé. Vérifiez votre courrier pour le confirmer." -#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:516 +#: pyaggr3g470r/views/views.py:268 pyaggr3g470r/views/views.py:515 msgid "Downloading articles..." msgstr "Téléchargement des articles." -#: pyaggr3g470r/views/views.py:333 +#: pyaggr3g470r/views/views.py:332 msgid "deleted." msgstr "supprimé." -#: pyaggr3g470r/views/views.py:336 +#: pyaggr3g470r/views/views.py:335 msgid "This article do not exist." msgstr "Cet article n'existe pas." -#: pyaggr3g470r/views/views.py:414 +#: pyaggr3g470r/views/views.py:413 msgid "Indexing database..." msgstr "Indexation la base de données..." -#: pyaggr3g470r/views/views.py:416 pyaggr3g470r/views/views.py:485 +#: pyaggr3g470r/views/views.py:415 pyaggr3g470r/views/views.py:484 msgid "An error occured" msgstr "Une erreur est survenue." -#: pyaggr3g470r/views/views.py:419 +#: pyaggr3g470r/views/views.py:418 msgid "Option not available on Heroku." msgstr "Option non disponible sur Heroku." -#: pyaggr3g470r/views/views.py:434 pyaggr3g470r/views/views.py:444 +#: pyaggr3g470r/views/views.py:433 pyaggr3g470r/views/views.py:443 msgid "Error when exporting articles." msgstr "Erreur lors de l'export des articles." -#: pyaggr3g470r/views/views.py:450 +#: pyaggr3g470r/views/views.py:449 msgid "Export format not supported." msgstr "Ce format d'export n'est pas supporté." -#: pyaggr3g470r/views/views.py:473 +#: pyaggr3g470r/views/views.py:472 msgid "Full text search is not yet implemented for Heroku." msgstr "La recherche rapide n'est pas supporté sur Heroku." -#: pyaggr3g470r/views/views.py:510 pyaggr3g470r/views/views.py:523 -#: pyaggr3g470r/views/views.py:531 +#: pyaggr3g470r/views/views.py:509 pyaggr3g470r/views/views.py:522 +#: pyaggr3g470r/views/views.py:530 msgid "File not allowed." msgstr "Fichier non autorisé." -#: pyaggr3g470r/views/views.py:515 +#: pyaggr3g470r/views/views.py:514 msgid "feeds imported." msgstr "flux importés." -#: pyaggr3g470r/views/views.py:518 +#: pyaggr3g470r/views/views.py:517 msgid "Impossible to import the new feeds." msgstr "Impossible d'importer les nouveaux flux." -#: pyaggr3g470r/views/views.py:527 +#: pyaggr3g470r/views/views.py:526 msgid "Account imported." msgstr "Compte importé." -#: pyaggr3g470r/views/views.py:529 +#: pyaggr3g470r/views/views.py:528 msgid "Impossible to import the account." msgstr "Impossible d'importer le compte." -#: pyaggr3g470r/views/views.py:571 +#: pyaggr3g470r/views/views.py:575 msgid "Feed successfully updated." msgstr "Flux mis à jour avec succès." -#: pyaggr3g470r/views/views.py:582 +#: pyaggr3g470r/views/views.py:586 msgid "Feed successfully created." msgstr "Flux créé avec succès." -#: pyaggr3g470r/views/views.py:585 +#: pyaggr3g470r/views/views.py:589 msgid "Downloading articles for the new feed..." msgstr "Téléchargement des articles du nouveau flux..." -#: pyaggr3g470r/views/views.py:589 +#: pyaggr3g470r/views/views.py:593 msgid "Feed already in the database." msgstr "Flux déjà dans la base de données." -#: pyaggr3g470r/views/views.py:596 +#: pyaggr3g470r/views/views.py:600 msgid "Edit the feed" msgstr "Éditez ce flux" -#: pyaggr3g470r/views/views.py:622 pyaggr3g470r/views/views.py:817 +#: pyaggr3g470r/views/views.py:626 pyaggr3g470r/views/views.py:821 msgid "successfully deleted." msgstr "supprimé avec succès." -#: pyaggr3g470r/views/views.py:640 pyaggr3g470r/views/views.py:767 -#: pyaggr3g470r/views/views.py:777 pyaggr3g470r/views/views.py:817 +#: pyaggr3g470r/views/views.py:644 pyaggr3g470r/views/views.py:771 +#: pyaggr3g470r/views/views.py:781 pyaggr3g470r/views/views.py:821 msgid "User" msgstr "Utilisateur" -#: pyaggr3g470r/views/views.py:641 pyaggr3g470r/views/views.py:767 +#: pyaggr3g470r/views/views.py:645 pyaggr3g470r/views/views.py:771 msgid "successfully updated." msgstr "mis à jour avec succès." -#: pyaggr3g470r/views/views.py:661 +#: pyaggr3g470r/views/views.py:665 msgid "Your account has been deleted." msgstr "Votre compte a été supprimé." -#: pyaggr3g470r/views/views.py:663 pyaggr3g470r/views/views.py:803 -#: pyaggr3g470r/views/views.py:819 pyaggr3g470r/views/views.py:847 +#: pyaggr3g470r/views/views.py:667 pyaggr3g470r/views/views.py:807 +#: pyaggr3g470r/views/views.py:823 pyaggr3g470r/views/views.py:851 msgid "This user does not exist." msgstr "Cet utilisateur n'existe pas." -#: pyaggr3g470r/views/views.py:677 +#: pyaggr3g470r/views/views.py:681 msgid "Articles deleted." msgstr "Articles supprimés." -#: pyaggr3g470r/views/views.py:691 +#: pyaggr3g470r/views/views.py:695 msgid "Your account has been confirmed." msgstr "Votre compte a été confirmé." -#: pyaggr3g470r/views/views.py:693 +#: pyaggr3g470r/views/views.py:697 msgid "Impossible to confirm this account." msgstr "Impossible de confirmer ce compte." -#: pyaggr3g470r/views/views.py:715 +#: pyaggr3g470r/views/views.py:719 msgid "New password sent to your address." msgstr "Nouveau mot de passe envoyé à votre adresse." -#: pyaggr3g470r/views/views.py:717 +#: pyaggr3g470r/views/views.py:721 msgid "Problem while sending your new password." msgstr "Problème lors de l'envoi de votre nouveau mot de passe." -#: pyaggr3g470r/views/views.py:742 +#: pyaggr3g470r/views/views.py:746 msgid "Problem while sending email" msgstr "Problème lors de l'envoi de l'email" -#: pyaggr3g470r/views/views.py:777 +#: pyaggr3g470r/views/views.py:781 msgid "successfully created." msgstr "créé avec succès." -#: pyaggr3g470r/views/views.py:786 +#: pyaggr3g470r/views/views.py:790 msgid "Edit the user" msgstr "Éditer cet utilisateur" -#: pyaggr3g470r/views/views.py:838 pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:842 pyaggr3g470r/views/views.py:848 msgid "Account of the user" msgstr "Compte de l'utilisateur" -#: pyaggr3g470r/views/views.py:838 +#: pyaggr3g470r/views/views.py:842 msgid "successfully activated." msgstr "activé avec succès." -#: pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:848 msgid "successfully disabled." msgstr "désactivé avec succès." -- cgit From c351b29b2181aabfdd115476ffa68df0c05a3a09 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 19 Mar 2015 11:54:08 +0100 Subject: Format the date with the adequat Babel filter. --- pyaggr3g470r/templates/history.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/history.html b/pyaggr3g470r/templates/history.html index b01ca032..6be54d71 100644 --- a/pyaggr3g470r/templates/history.html +++ b/pyaggr3g470r/templates/history.html @@ -17,7 +17,7 @@
    • {{ article | month_name }} : {{ articles_counter[article] }} articles
    • {% else %} {% for article in articles | sort(attribute="date", reverse = True) %} -
    • {{ article.date }} - {{ article.title | safe }}
    • +
    • {{ article.date | datetime }} - {{ article.title | safe }}
    • {% endfor %} {% endif %} {% endfor %} -- cgit From c94a05150f22d0fef073efdd1ef6f1debb51dbab Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 23 Mar 2015 19:21:30 +0100 Subject: Fixed a minor bug in the '/feed' page. --- messages.pot | 36 ++++++++--------- pyaggr3g470r/templates/feed.html | 14 +++---- .../translations/fr/LC_MESSAGES/messages.mo | Bin 15318 -> 15239 bytes .../translations/fr/LC_MESSAGES/messages.po | 43 ++++++++++----------- pyaggr3g470r/views/feed.py | 8 ++-- 5 files changed, 47 insertions(+), 54 deletions(-) diff --git a/messages.pot b/messages.pot index e54e116e..d4d54557 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-17 18:22+0100\n" +"POT-Creation-Date: 2015-03-23 19:20+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -299,55 +299,51 @@ msgstr "" msgid "articles" msgstr "" -#: pyaggr3g470r/templates/feed.html:14 -msgid "of the database" +#: pyaggr3g470r/templates/feed.html:13 +msgid "Address of the feed" +msgstr "" + +#: pyaggr3g470r/templates/feed.html:15 +msgid "Address of the site" msgstr "" -#: pyaggr3g470r/templates/feed.html:18 +#: pyaggr3g470r/templates/feed.html:21 msgid "Last download:" msgstr "" -#: pyaggr3g470r/templates/feed.html:22 +#: pyaggr3g470r/templates/feed.html:25 msgid "" "That feed has encountered too much consecutive errors and won't be " "retrieved anymore." msgstr "" -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:27 msgid "" "The download of this feed has encountered some problems. However its " "error counter will be reinitialized at the next successful retrieving." msgstr "" -#: pyaggr3g470r/templates/feed.html:28 -msgid "Here's the last error encountered while retrieving this feed:" -msgstr "" - #: pyaggr3g470r/templates/feed.html:31 -msgid "Address of the feed" -msgstr "" - -#: pyaggr3g470r/templates/feed.html:33 -msgid "Address of the site" +msgid "Here's the last error encountered while retrieving this feed:" msgstr "" -#: pyaggr3g470r/templates/feed.html:37 +#: pyaggr3g470r/templates/feed.html:35 msgid "The last article was posted" msgstr "" -#: pyaggr3g470r/templates/feed.html:37 +#: pyaggr3g470r/templates/feed.html:35 msgid "day(s) ago." msgstr "" -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "Daily average" msgstr "" -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "between the" msgstr "" -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "and the" msgstr "" diff --git a/pyaggr3g470r/templates/feed.html b/pyaggr3g470r/templates/feed.html index 4b050573..c7dfecc2 100644 --- a/pyaggr3g470r/templates/feed.html +++ b/pyaggr3g470r/templates/feed.html @@ -9,11 +9,14 @@

    - {{ _('This feed contains') }} {{ feed.articles.all()|count }} {{ _('articles') }} - {% if nb_articles != 0 %} - ({{ ((feed.articles.all()|count * 100 ) / nb_articles) | round(2, 'floor') }}% {{ _('of the database') }}).
    + {{ _('This feed contains') }} {{ feed.articles.all()|count }} {{ _('articles') }}.
    + {{ _('Address of the feed') }}: {{ feed.link }}
    + {% if feed.site_link != "" %} + {{ _('Address of the site') }}: {{ feed.site_link }}
    {% endif %} +
    + {% if feed.last_retrieved %} {{ _("Last download:") }} {{ feed.last_retrieved | datetime }}
    {% endif %} @@ -28,11 +31,6 @@ {{ _("Here's the last error encountered while retrieving this feed:") }}

    {{ feed.last_error }}

    {% endif %} - {{ _('Address of the feed') }}: {{ feed.link }}
    - {% if feed.site_link != "" %} - {{ _('Address of the site') }}: {{ feed.site_link }}
    - {% endif %} - {% if feed.articles.all()|count != 0 %} {{ _('The last article was posted') }} {{ elapsed.days }} {{ _('day(s) ago.') }}
    {{ _('Daily average') }}: {{ average }}, {{ _('between the') }} {{ first_post_date | datetime }} {{ _('and the') }} {{ end_post_date | datetime }}. diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index 8f232509..9f133872 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index fdf98b3b..4a22ef8c 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-17 18:22+0100\n" -"PO-Revision-Date: 2015-03-17 18:22+0100\n" +"POT-Creation-Date: 2015-03-23 19:20+0100\n" +"PO-Revision-Date: 2015-03-23 19:21+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -319,22 +319,26 @@ msgstr "Ce flux contient" msgid "articles" msgstr "articles" -#: pyaggr3g470r/templates/feed.html:14 -msgid "of the database" -msgstr "de la base de données" +#: pyaggr3g470r/templates/feed.html:13 +msgid "Address of the feed" +msgstr "Adresse du flux" -#: pyaggr3g470r/templates/feed.html:18 +#: pyaggr3g470r/templates/feed.html:15 +msgid "Address of the site" +msgstr "Adresse du site" + +#: pyaggr3g470r/templates/feed.html:21 msgid "Last download:" msgstr "Dernier téléchargement:" -#: pyaggr3g470r/templates/feed.html:22 +#: pyaggr3g470r/templates/feed.html:25 msgid "" "That feed has encountered too much consecutive errors and won't be retrieved " "anymore." msgstr "" "Ce flux a rencontré trop d'erreurs consécutives et ne sera plus récupéré." -#: pyaggr3g470r/templates/feed.html:24 +#: pyaggr3g470r/templates/feed.html:27 msgid "" "The download of this feed has encountered some problems. However its error " "counter will be reinitialized at the next successful retrieving." @@ -343,35 +347,27 @@ msgstr "" "compteur d'erreurs sera réinitialisé lors de la prochaine récupération " "réussie." -#: pyaggr3g470r/templates/feed.html:28 +#: pyaggr3g470r/templates/feed.html:31 msgid "Here's the last error encountered while retrieving this feed:" msgstr "Voici la dernière erreur survenue lors de la récupération ce flux:" -#: pyaggr3g470r/templates/feed.html:31 -msgid "Address of the feed" -msgstr "Adresse du flux" - -#: pyaggr3g470r/templates/feed.html:33 -msgid "Address of the site" -msgstr "Adresse du site" - -#: pyaggr3g470r/templates/feed.html:37 +#: pyaggr3g470r/templates/feed.html:35 msgid "The last article was posted" msgstr "Le dernier article a été posté il y a" -#: pyaggr3g470r/templates/feed.html:37 +#: pyaggr3g470r/templates/feed.html:35 msgid "day(s) ago." msgstr "jours." -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "Daily average" msgstr "Moyenne journalière" -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "between the" msgstr "entre le" -#: pyaggr3g470r/templates/feed.html:38 +#: pyaggr3g470r/templates/feed.html:36 msgid "and the" msgstr "et le" @@ -894,6 +890,9 @@ msgstr "activé avec succès." msgid "successfully disabled." msgstr "désactivé avec succès." +#~ msgid "of the database" +#~ msgstr "de la base de données" + #~ msgid "Email notification" #~ msgstr "Notification par email" diff --git a/pyaggr3g470r/views/feed.py b/pyaggr3g470r/views/feed.py index 2e39ee4b..4fe4e5da 100644 --- a/pyaggr3g470r/views/feed.py +++ b/pyaggr3g470r/views/feed.py @@ -3,6 +3,7 @@ from datetime import datetime from flask import Blueprint, g, render_template +from sqlalchemy import desc from pyaggr3g470r import controllers, utils from pyaggr3g470r.decorators import pyagg_default_decorator, \ @@ -25,9 +26,9 @@ def feed(feed_id=None): "Presents detailed information about a feed." feed = controllers.FeedController(g.user.id).get(id=feed_id) word_size = 6 - articles = controllers.ArticleController(g.user.id)\ - .read(feed_id=feed_id).all() - nb_articles = controllers.ArticleController(g.user.id).read().count() + articles = controllers.ArticleController(g.user.id) \ + .read(feed_id=feed_id) \ + .order_by(desc("Article.date")).all() top_words = utils.top_words(articles, n=50, size=int(word_size)) tag_cloud = utils.tag_cloud(top_words) @@ -49,5 +50,4 @@ def feed(feed_id=None): feed=feed, tag_cloud=tag_cloud, first_post_date=first_article, end_post_date=last_article, - nb_articles=nb_articles, average=average, delta=delta, elapsed=elapsed) -- cgit From 5e31ec379db43f6ecfdde6ebdc155e7896338698 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 23 Mar 2015 19:27:42 +0100 Subject: Use the 'safe' Jinja filter to prevent bad html code. --- pyaggr3g470r/templates/feed.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/feed.html b/pyaggr3g470r/templates/feed.html index c7dfecc2..3d6bb3c0 100644 --- a/pyaggr3g470r/templates/feed.html +++ b/pyaggr3g470r/templates/feed.html @@ -28,7 +28,7 @@ {% endif %} {% if feed.last_error %} - {{ _("Here's the last error encountered while retrieving this feed:") }}
    {{ feed.last_error }}

    + {{ _("Here's the last error encountered while retrieving this feed:") }}
    {{ feed.last_error | safe }}

    {% endif %} {% if feed.articles.all()|count != 0 %} -- cgit From b7951227d3daf1723dc7805155cc68e4b8ec779d Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 23 Mar 2015 19:29:59 +0100 Subject: Previous commit is useless... --- pyaggr3g470r/templates/feed.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/feed.html b/pyaggr3g470r/templates/feed.html index 3d6bb3c0..c7dfecc2 100644 --- a/pyaggr3g470r/templates/feed.html +++ b/pyaggr3g470r/templates/feed.html @@ -28,7 +28,7 @@ {% endif %} {% if feed.last_error %} - {{ _("Here's the last error encountered while retrieving this feed:") }}
    {{ feed.last_error | safe }}

    + {{ _("Here's the last error encountered while retrieving this feed:") }}
    {{ feed.last_error }}

    {% endif %} {% if feed.articles.all()|count != 0 %} -- cgit From 89ad1ea47e3feaee8525a25980e33f2a289c039a Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 23 Mar 2015 21:47:26 +0100 Subject: The manual retrieving of news is solely available for administrator, on the Heroku platform. --- messages.pot | 94 +++++++++++--------- .../translations/fr/LC_MESSAGES/messages.mo | Bin 15239 -> 15486 bytes .../translations/fr/LC_MESSAGES/messages.po | 98 +++++++++++---------- pyaggr3g470r/views/views.py | 8 +- 4 files changed, 109 insertions(+), 91 deletions(-) diff --git a/messages.pot b/messages.pot index d4d54557..a8da28c1 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-23 19:20+0100\n" +"POT-Creation-Date: 2015-03-23 21:46+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -449,11 +449,11 @@ msgid "Unread" msgstr "" #: pyaggr3g470r/templates/home.html:81 -#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:626 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:630 msgid "Feed" msgstr "" -#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:332 +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:336 msgid "Article" msgstr "" @@ -481,7 +481,7 @@ msgstr "" msgid "Mark all as read" msgstr "" -#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:613 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:617 msgid "Add a feed" msgstr "" @@ -658,7 +658,7 @@ msgid "You are going to delete this account." msgstr "" #: pyaggr3g470r/templates/admin/dashboard.html:45 -#: pyaggr3g470r/views/views.py:793 +#: pyaggr3g470r/views/views.py:797 msgid "Add a new user" msgstr "" @@ -710,7 +710,7 @@ msgstr "" msgid "Email already used." msgstr "" -#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:848 msgid "Problem while sending activation email" msgstr "" @@ -718,146 +718,152 @@ msgstr "" msgid "Your account has been created. Check your mail to confirm it." msgstr "" -#: pyaggr3g470r/views/views.py:268 pyaggr3g470r/views/views.py:515 +#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:519 msgid "Downloading articles..." msgstr "" -#: pyaggr3g470r/views/views.py:332 +#: pyaggr3g470r/views/views.py:271 +msgid "" +"The manual retrieving of news is only available for administrator, on the" +" Heroku platform." +msgstr "" + +#: pyaggr3g470r/views/views.py:336 msgid "deleted." msgstr "" -#: pyaggr3g470r/views/views.py:335 +#: pyaggr3g470r/views/views.py:339 msgid "This article do not exist." msgstr "" -#: pyaggr3g470r/views/views.py:413 +#: pyaggr3g470r/views/views.py:417 msgid "Indexing database..." msgstr "" -#: pyaggr3g470r/views/views.py:415 pyaggr3g470r/views/views.py:484 +#: pyaggr3g470r/views/views.py:419 pyaggr3g470r/views/views.py:488 msgid "An error occured" msgstr "" -#: pyaggr3g470r/views/views.py:418 +#: pyaggr3g470r/views/views.py:422 msgid "Option not available on Heroku." msgstr "" -#: pyaggr3g470r/views/views.py:433 pyaggr3g470r/views/views.py:443 +#: pyaggr3g470r/views/views.py:437 pyaggr3g470r/views/views.py:447 msgid "Error when exporting articles." msgstr "" -#: pyaggr3g470r/views/views.py:449 +#: pyaggr3g470r/views/views.py:453 msgid "Export format not supported." msgstr "" -#: pyaggr3g470r/views/views.py:472 +#: pyaggr3g470r/views/views.py:476 msgid "Full text search is not yet implemented for Heroku." msgstr "" -#: pyaggr3g470r/views/views.py:509 pyaggr3g470r/views/views.py:522 -#: pyaggr3g470r/views/views.py:530 +#: pyaggr3g470r/views/views.py:513 pyaggr3g470r/views/views.py:526 +#: pyaggr3g470r/views/views.py:534 msgid "File not allowed." msgstr "" -#: pyaggr3g470r/views/views.py:514 +#: pyaggr3g470r/views/views.py:518 msgid "feeds imported." msgstr "" -#: pyaggr3g470r/views/views.py:517 +#: pyaggr3g470r/views/views.py:521 msgid "Impossible to import the new feeds." msgstr "" -#: pyaggr3g470r/views/views.py:526 +#: pyaggr3g470r/views/views.py:530 msgid "Account imported." msgstr "" -#: pyaggr3g470r/views/views.py:528 +#: pyaggr3g470r/views/views.py:532 msgid "Impossible to import the account." msgstr "" -#: pyaggr3g470r/views/views.py:575 +#: pyaggr3g470r/views/views.py:579 msgid "Feed successfully updated." msgstr "" -#: pyaggr3g470r/views/views.py:586 +#: pyaggr3g470r/views/views.py:590 msgid "Feed successfully created." msgstr "" -#: pyaggr3g470r/views/views.py:589 +#: pyaggr3g470r/views/views.py:593 msgid "Downloading articles for the new feed..." msgstr "" -#: pyaggr3g470r/views/views.py:593 +#: pyaggr3g470r/views/views.py:597 msgid "Feed already in the database." msgstr "" -#: pyaggr3g470r/views/views.py:600 +#: pyaggr3g470r/views/views.py:604 msgid "Edit the feed" msgstr "" -#: pyaggr3g470r/views/views.py:626 pyaggr3g470r/views/views.py:821 +#: pyaggr3g470r/views/views.py:630 pyaggr3g470r/views/views.py:825 msgid "successfully deleted." msgstr "" -#: pyaggr3g470r/views/views.py:644 pyaggr3g470r/views/views.py:771 -#: pyaggr3g470r/views/views.py:781 pyaggr3g470r/views/views.py:821 +#: pyaggr3g470r/views/views.py:648 pyaggr3g470r/views/views.py:775 +#: pyaggr3g470r/views/views.py:785 pyaggr3g470r/views/views.py:825 msgid "User" msgstr "" -#: pyaggr3g470r/views/views.py:645 pyaggr3g470r/views/views.py:771 +#: pyaggr3g470r/views/views.py:649 pyaggr3g470r/views/views.py:775 msgid "successfully updated." msgstr "" -#: pyaggr3g470r/views/views.py:665 +#: pyaggr3g470r/views/views.py:669 msgid "Your account has been deleted." msgstr "" -#: pyaggr3g470r/views/views.py:667 pyaggr3g470r/views/views.py:807 -#: pyaggr3g470r/views/views.py:823 pyaggr3g470r/views/views.py:851 +#: pyaggr3g470r/views/views.py:671 pyaggr3g470r/views/views.py:811 +#: pyaggr3g470r/views/views.py:827 pyaggr3g470r/views/views.py:855 msgid "This user does not exist." msgstr "" -#: pyaggr3g470r/views/views.py:681 +#: pyaggr3g470r/views/views.py:685 msgid "Articles deleted." msgstr "" -#: pyaggr3g470r/views/views.py:695 +#: pyaggr3g470r/views/views.py:699 msgid "Your account has been confirmed." msgstr "" -#: pyaggr3g470r/views/views.py:697 +#: pyaggr3g470r/views/views.py:701 msgid "Impossible to confirm this account." msgstr "" -#: pyaggr3g470r/views/views.py:719 +#: pyaggr3g470r/views/views.py:723 msgid "New password sent to your address." msgstr "" -#: pyaggr3g470r/views/views.py:721 +#: pyaggr3g470r/views/views.py:725 msgid "Problem while sending your new password." msgstr "" -#: pyaggr3g470r/views/views.py:746 +#: pyaggr3g470r/views/views.py:750 msgid "Problem while sending email" msgstr "" -#: pyaggr3g470r/views/views.py:781 +#: pyaggr3g470r/views/views.py:785 msgid "successfully created." msgstr "" -#: pyaggr3g470r/views/views.py:790 +#: pyaggr3g470r/views/views.py:794 msgid "Edit the user" msgstr "" -#: pyaggr3g470r/views/views.py:842 pyaggr3g470r/views/views.py:848 +#: pyaggr3g470r/views/views.py:846 pyaggr3g470r/views/views.py:852 msgid "Account of the user" msgstr "" -#: pyaggr3g470r/views/views.py:842 +#: pyaggr3g470r/views/views.py:846 msgid "successfully activated." msgstr "" -#: pyaggr3g470r/views/views.py:848 +#: pyaggr3g470r/views/views.py:852 msgid "successfully disabled." msgstr "" diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index 9f133872..72a16eb2 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index 4a22ef8c..8561a0d8 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-23 19:20+0100\n" -"PO-Revision-Date: 2015-03-23 19:21+0100\n" +"POT-Creation-Date: 2015-03-23 21:46+0100\n" +"PO-Revision-Date: 2015-03-23 21:47+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -478,11 +478,11 @@ msgid "Unread" msgstr "Non lus" #: pyaggr3g470r/templates/home.html:81 -#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:626 +#: pyaggr3g470r/templates/admin/user.html:42 pyaggr3g470r/views/views.py:630 msgid "Feed" msgstr "Flux" -#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:332 +#: pyaggr3g470r/templates/home.html:82 pyaggr3g470r/views/views.py:336 msgid "Article" msgstr "Article" @@ -510,7 +510,7 @@ msgstr "Télécharger" msgid "Mark all as read" msgstr "Marquer tout comme lu" -#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:613 +#: pyaggr3g470r/templates/layout.html:100 pyaggr3g470r/views/views.py:617 msgid "Add a feed" msgstr "Ajouter un flux" @@ -687,7 +687,7 @@ msgid "You are going to delete this account." msgstr "Vous allez supprimer ce compte." #: pyaggr3g470r/templates/admin/dashboard.html:45 -#: pyaggr3g470r/views/views.py:793 +#: pyaggr3g470r/views/views.py:797 msgid "Add a new user" msgstr "Ajouter un nouvel utilisateur" @@ -739,7 +739,7 @@ msgstr "L'auto-enregistrement est désactivé." msgid "Email already used." msgstr "Email déjà utilisé." -#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:844 +#: pyaggr3g470r/views/views.py:217 pyaggr3g470r/views/views.py:848 msgid "Problem while sending activation email" msgstr "Problème lors de l'envoi d'email d'activation" @@ -747,146 +747,154 @@ msgstr "Problème lors de l'envoi d'email d'activation" msgid "Your account has been created. Check your mail to confirm it." msgstr "Votre compte a été créé. Vérifiez votre courrier pour le confirmer." -#: pyaggr3g470r/views/views.py:268 pyaggr3g470r/views/views.py:515 +#: pyaggr3g470r/views/views.py:269 pyaggr3g470r/views/views.py:519 msgid "Downloading articles..." msgstr "Téléchargement des articles." -#: pyaggr3g470r/views/views.py:332 +#: pyaggr3g470r/views/views.py:271 +msgid "" +"The manual retrieving of news is only available for administrator, on the " +"Heroku platform." +msgstr "" +"La récupération manuelle de nouvelles est disponible uniquement pour " +"l'administrateur, sur la plate-forme Heroku." + +#: pyaggr3g470r/views/views.py:336 msgid "deleted." msgstr "supprimé." -#: pyaggr3g470r/views/views.py:335 +#: pyaggr3g470r/views/views.py:339 msgid "This article do not exist." msgstr "Cet article n'existe pas." -#: pyaggr3g470r/views/views.py:413 +#: pyaggr3g470r/views/views.py:417 msgid "Indexing database..." msgstr "Indexation la base de données..." -#: pyaggr3g470r/views/views.py:415 pyaggr3g470r/views/views.py:484 +#: pyaggr3g470r/views/views.py:419 pyaggr3g470r/views/views.py:488 msgid "An error occured" msgstr "Une erreur est survenue." -#: pyaggr3g470r/views/views.py:418 +#: pyaggr3g470r/views/views.py:422 msgid "Option not available on Heroku." msgstr "Option non disponible sur Heroku." -#: pyaggr3g470r/views/views.py:433 pyaggr3g470r/views/views.py:443 +#: pyaggr3g470r/views/views.py:437 pyaggr3g470r/views/views.py:447 msgid "Error when exporting articles." msgstr "Erreur lors de l'export des articles." -#: pyaggr3g470r/views/views.py:449 +#: pyaggr3g470r/views/views.py:453 msgid "Export format not supported." msgstr "Ce format d'export n'est pas supporté." -#: pyaggr3g470r/views/views.py:472 +#: pyaggr3g470r/views/views.py:476 msgid "Full text search is not yet implemented for Heroku." msgstr "La recherche rapide n'est pas supporté sur Heroku." -#: pyaggr3g470r/views/views.py:509 pyaggr3g470r/views/views.py:522 -#: pyaggr3g470r/views/views.py:530 +#: pyaggr3g470r/views/views.py:513 pyaggr3g470r/views/views.py:526 +#: pyaggr3g470r/views/views.py:534 msgid "File not allowed." msgstr "Fichier non autorisé." -#: pyaggr3g470r/views/views.py:514 +#: pyaggr3g470r/views/views.py:518 msgid "feeds imported." msgstr "flux importés." -#: pyaggr3g470r/views/views.py:517 +#: pyaggr3g470r/views/views.py:521 msgid "Impossible to import the new feeds." msgstr "Impossible d'importer les nouveaux flux." -#: pyaggr3g470r/views/views.py:526 +#: pyaggr3g470r/views/views.py:530 msgid "Account imported." msgstr "Compte importé." -#: pyaggr3g470r/views/views.py:528 +#: pyaggr3g470r/views/views.py:532 msgid "Impossible to import the account." msgstr "Impossible d'importer le compte." -#: pyaggr3g470r/views/views.py:575 +#: pyaggr3g470r/views/views.py:579 msgid "Feed successfully updated." msgstr "Flux mis à jour avec succès." -#: pyaggr3g470r/views/views.py:586 +#: pyaggr3g470r/views/views.py:590 msgid "Feed successfully created." msgstr "Flux créé avec succès." -#: pyaggr3g470r/views/views.py:589 +#: pyaggr3g470r/views/views.py:593 msgid "Downloading articles for the new feed..." msgstr "Téléchargement des articles du nouveau flux..." -#: pyaggr3g470r/views/views.py:593 +#: pyaggr3g470r/views/views.py:597 msgid "Feed already in the database." msgstr "Flux déjà dans la base de données." -#: pyaggr3g470r/views/views.py:600 +#: pyaggr3g470r/views/views.py:604 msgid "Edit the feed" msgstr "Éditez ce flux" -#: pyaggr3g470r/views/views.py:626 pyaggr3g470r/views/views.py:821 +#: pyaggr3g470r/views/views.py:630 pyaggr3g470r/views/views.py:825 msgid "successfully deleted." msgstr "supprimé avec succès." -#: pyaggr3g470r/views/views.py:644 pyaggr3g470r/views/views.py:771 -#: pyaggr3g470r/views/views.py:781 pyaggr3g470r/views/views.py:821 +#: pyaggr3g470r/views/views.py:648 pyaggr3g470r/views/views.py:775 +#: pyaggr3g470r/views/views.py:785 pyaggr3g470r/views/views.py:825 msgid "User" msgstr "Utilisateur" -#: pyaggr3g470r/views/views.py:645 pyaggr3g470r/views/views.py:771 +#: pyaggr3g470r/views/views.py:649 pyaggr3g470r/views/views.py:775 msgid "successfully updated." msgstr "mis à jour avec succès." -#: pyaggr3g470r/views/views.py:665 +#: pyaggr3g470r/views/views.py:669 msgid "Your account has been deleted." msgstr "Votre compte a été supprimé." -#: pyaggr3g470r/views/views.py:667 pyaggr3g470r/views/views.py:807 -#: pyaggr3g470r/views/views.py:823 pyaggr3g470r/views/views.py:851 +#: pyaggr3g470r/views/views.py:671 pyaggr3g470r/views/views.py:811 +#: pyaggr3g470r/views/views.py:827 pyaggr3g470r/views/views.py:855 msgid "This user does not exist." msgstr "Cet utilisateur n'existe pas." -#: pyaggr3g470r/views/views.py:681 +#: pyaggr3g470r/views/views.py:685 msgid "Articles deleted." msgstr "Articles supprimés." -#: pyaggr3g470r/views/views.py:695 +#: pyaggr3g470r/views/views.py:699 msgid "Your account has been confirmed." msgstr "Votre compte a été confirmé." -#: pyaggr3g470r/views/views.py:697 +#: pyaggr3g470r/views/views.py:701 msgid "Impossible to confirm this account." msgstr "Impossible de confirmer ce compte." -#: pyaggr3g470r/views/views.py:719 +#: pyaggr3g470r/views/views.py:723 msgid "New password sent to your address." msgstr "Nouveau mot de passe envoyé à votre adresse." -#: pyaggr3g470r/views/views.py:721 +#: pyaggr3g470r/views/views.py:725 msgid "Problem while sending your new password." msgstr "Problème lors de l'envoi de votre nouveau mot de passe." -#: pyaggr3g470r/views/views.py:746 +#: pyaggr3g470r/views/views.py:750 msgid "Problem while sending email" msgstr "Problème lors de l'envoi de l'email" -#: pyaggr3g470r/views/views.py:781 +#: pyaggr3g470r/views/views.py:785 msgid "successfully created." msgstr "créé avec succès." -#: pyaggr3g470r/views/views.py:790 +#: pyaggr3g470r/views/views.py:794 msgid "Edit the user" msgstr "Éditer cet utilisateur" -#: pyaggr3g470r/views/views.py:842 pyaggr3g470r/views/views.py:848 +#: pyaggr3g470r/views/views.py:846 pyaggr3g470r/views/views.py:852 msgid "Account of the user" msgstr "Compte de l'utilisateur" -#: pyaggr3g470r/views/views.py:842 +#: pyaggr3g470r/views/views.py:846 msgid "successfully activated." msgstr "activé avec succès." -#: pyaggr3g470r/views/views.py:848 +#: pyaggr3g470r/views/views.py:852 msgid "successfully disabled." msgstr "désactivé avec succès." diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index 9aefd6b1..dc6bfead 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -264,8 +264,12 @@ def fetch(feed_id=None): Triggers the download of news. News are downloaded in a separated process, mandatory for Heroku. """ - utils.fetch(g.user.id, feed_id) - flash(gettext("Downloading articles..."), 'info') + if not conf.ON_HEROKU or g.user.is_admin(): + utils.fetch(g.user.id, feed_id) + flash(gettext("Downloading articles..."), "info") + else: + flash(gettext("The manual retrieving of news is only available " + + "for administrator, on the Heroku platform."), "info") return redirect(redirect_url()) @app.route('/about', methods=['GET']) -- cgit From d75d8f6783aad6f52e7c6db00b0f58b3187acced Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 24 Mar 2015 21:16:01 +0100 Subject: Added a script to install pyAggr3g470r on a server. --- documentation/deployment.rst | 6 ++---- install.sh | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 install.sh diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 3aedbb60..6d1b119c 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -81,12 +81,9 @@ Deploying the application on a traditional server .. code-block:: bash - $ sudo apt-get install python libpq-dev python-dev python-pip build-essential git - $ sudo apt-get install libxml2-dev libxslt1-dev # for lxml $ git clone https://bitbucket.org/cedricbonhomme/pyaggr3g470r.git $ cd pyaggr3g470r - $ sudo pip install --upgrade -r requirements.txt - $ cp conf/conf.cfg-sample conf/conf.cfg + $ ./install.sh If you want to use PostgreSQL ''''''''''''''''''''''''''''' @@ -94,6 +91,7 @@ If you want to use PostgreSQL .. code-block:: bash $ sudo apt-get install postgresql postgresql-server-dev-9.3 postgresql-client + $ sudo pip install psycopg2 $ echo "127.0.0.1:5432:aggregator:pgsqluser:pgsqlpwd" > ~/.pgpass $ chmod 700 ~/.pgpass $ sudo -u postgres createuser pgsqluser --no-superuser --createdb --no-createrole diff --git a/install.sh b/install.sh new file mode 100644 index 00000000..8d62a0b6 --- /dev/null +++ b/install.sh @@ -0,0 +1,16 @@ +#! /usr/bin/env sh + +# +# This script install all dependencies for pyAggr3g470r. +# psycopg2 is removed from the requirements.txt file since it is only required +# if the user wants to use Postgres. Postgres is generally used on the Heroku +# platform. +# + +sudo apt-get install python libpq-dev python-dev python-pip build-essential git +sudo apt-get install libxml2-dev libxslt1-dev # for lxml + +sed -i '/psycopg2/d' requirements.txt +sudo pip install --upgrade -r requirements.txt + +cp conf/conf.cfg-sample conf/conf.cfg -- cgit From 385c6cb95059e3aac04c85036de968c9ddc029ed Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 24 Mar 2015 21:51:38 +0100 Subject: Improved the installation script (not yet tested). --- documentation/deployment.rst | 27 ++++----------------------- install.sh | 29 +++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 27 deletions(-) mode change 100644 => 100755 install.sh diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 6d1b119c..c95dfe91 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -82,39 +82,20 @@ Deploying the application on a traditional server .. code-block:: bash $ git clone https://bitbucket.org/cedricbonhomme/pyaggr3g470r.git - $ cd pyaggr3g470r - $ ./install.sh + $ cd pyaggr3g470r/ If you want to use PostgreSQL ''''''''''''''''''''''''''''' - .. code-block:: bash - $ sudo apt-get install postgresql postgresql-server-dev-9.3 postgresql-client - $ sudo pip install psycopg2 - $ echo "127.0.0.1:5432:aggregator:pgsqluser:pgsqlpwd" > ~/.pgpass - $ chmod 700 ~/.pgpass - $ sudo -u postgres createuser pgsqluser --no-superuser --createdb --no-createrole - $ createdb aggregator --no-password - $ echo "ALTER USER pgsqluser WITH ENCRYPTED PASSWORD 'pgsqlpwd';" | sudo -u postgres psql - $ echo "GRANT ALL PRIVILEGES ON DATABASE aggregator TO pgsqluser;" | sudo -u postgres psql - -Edit the configuration file with the line: - -.. code-block:: cfg - - [database] - uri = postgres://pgsqluser:pgsqlpwd@127.0.0.1:5433/aggregator + $ ./install.sh postgre If you want to use SQLite ''''''''''''''''''''''''' -Just edit the configuration file with the line: - -.. code-block:: cfg +.. code-block:: bash - [database] - uri = sqlite+pysqlite:///pyAggr3g470r.db + $ ./install.sh sqlite Finally: diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 8d62a0b6..232e3902 --- a/install.sh +++ b/install.sh @@ -1,10 +1,7 @@ -#! /usr/bin/env sh +#! /usr/bin/env bash # # This script install all dependencies for pyAggr3g470r. -# psycopg2 is removed from the requirements.txt file since it is only required -# if the user wants to use Postgres. Postgres is generally used on the Heroku -# platform. # sudo apt-get install python libpq-dev python-dev python-pip build-essential git @@ -13,4 +10,28 @@ sudo apt-get install libxml2-dev libxslt1-dev # for lxml sed -i '/psycopg2/d' requirements.txt sudo pip install --upgrade -r requirements.txt +# Initializes the configuration file cp conf/conf.cfg-sample conf/conf.cfg + +# Delete default database configuration +sed -i '/database/d' conf/conf.cfg +sed -i '/uri/d' conf/conf.cfg + +if [ "$1" == postgre ]; then + sudo apt-get install -y postgresql postgresql-server-dev-9.3 postgresql-client + sudo pip install psycopg2 + echo "127.0.0.1:5432:aggregator:pgsqluser:pgsqlpwd" > ~/.pgpass + chmod 700 ~/.pgpass + sudo -u postgres createuser pgsqluser --no-superuser --createdb --no-createrole + createdb aggregator --no-password + echo "ALTER USER pgsqluser WITH ENCRYPTED PASSWORD 'pgsqlpwd';" | sudo -u postgres psql + echo "GRANT ALL PRIVILEGES ON DATABASE aggregator TO pgsqluser;" | sudo -u postgres psql + + # Add configuration lines for PostgreSQL + echo '[database]' >> conf/conf.cfg + echo 'uri = postgres://pgsqluser:pgsqlpwd@127.0.0.1:5432/aggregator' >> conf/conf.cfg +elif [ "$1" == sqlite ]; then + # Add configuration lines for SQLite + echo '[database]' >> conf/conf.cfg + echo 'uri = sqlite+pysqlite:///pyAggr3g470r.db' >> conf/conf.cfg +fi -- cgit From 8971cbed055ea19c0e0d507e8a38e013c2decc10 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 25 Mar 2015 07:44:04 +0100 Subject: Improved installation script (tested with PostgreSQL, problem with SQLite because pysqlite is not yet ported to Python 3). --- documentation/deployment.rst | 1 - install.sh | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index c95dfe91..158eda7d 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -102,7 +102,6 @@ Finally: .. code-block:: bash - $ python manager.py db_create $ python runserver.py * Running on http://0.0.0.0:5000/ * Restarting with reloader diff --git a/install.sh b/install.sh index 232e3902..0b187dea 100755 --- a/install.sh +++ b/install.sh @@ -1,7 +1,8 @@ #! /usr/bin/env bash # -# This script install all dependencies for pyAggr3g470r. +# This script install all dependencies and configure pyAggr3g470r +# for Python 3. # sudo apt-get install python libpq-dev python-dev python-pip build-essential git @@ -31,7 +32,11 @@ if [ "$1" == postgre ]; then echo '[database]' >> conf/conf.cfg echo 'uri = postgres://pgsqluser:pgsqlpwd@127.0.0.1:5432/aggregator' >> conf/conf.cfg elif [ "$1" == sqlite ]; then + sudo pip install pysqlite # not working with Python 3! # Add configuration lines for SQLite echo '[database]' >> conf/conf.cfg echo 'uri = sqlite+pysqlite:///pyAggr3g470r.db' >> conf/conf.cfg fi + +python manager.py db_empty +python manager.py db_create \ No newline at end of file -- cgit From eea3391f37c1c49d6721f360cde34dde0d6ae6ce Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 25 Mar 2015 07:51:17 +0100 Subject: Added '-y' option to when installing dependencies with apt. --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 0b187dea..09144fe1 100755 --- a/install.sh +++ b/install.sh @@ -5,8 +5,8 @@ # for Python 3. # -sudo apt-get install python libpq-dev python-dev python-pip build-essential git -sudo apt-get install libxml2-dev libxslt1-dev # for lxml +sudo apt-get install -y python libpq-dev python-dev python-pip build-essential git +sudo apt-get install -y libxml2-dev libxslt1-dev # for lxml sed -i '/psycopg2/d' requirements.txt sudo pip install --upgrade -r requirements.txt -- cgit From 1a4a12081f9a55a851cbfcb0a0f171450c9873ce Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 26 Mar 2015 07:28:03 +0100 Subject: Renamed a parameter of the install.sh script. --- documentation/deployment.rst | 2 +- install.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 158eda7d..0402afd3 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -88,7 +88,7 @@ If you want to use PostgreSQL ''''''''''''''''''''''''''''' .. code-block:: bash - $ ./install.sh postgre + $ ./install.sh postgres If you want to use SQLite ''''''''''''''''''''''''' diff --git a/install.sh b/install.sh index 09144fe1..101e388c 100755 --- a/install.sh +++ b/install.sh @@ -18,7 +18,7 @@ cp conf/conf.cfg-sample conf/conf.cfg sed -i '/database/d' conf/conf.cfg sed -i '/uri/d' conf/conf.cfg -if [ "$1" == postgre ]; then +if [ "$1" == postgres ]; then sudo apt-get install -y postgresql postgresql-server-dev-9.3 postgresql-client sudo pip install psycopg2 echo "127.0.0.1:5432:aggregator:pgsqluser:pgsqlpwd" > ~/.pgpass @@ -39,4 +39,4 @@ elif [ "$1" == sqlite ]; then fi python manager.py db_empty -python manager.py db_create \ No newline at end of file +python manager.py db_create -- cgit From 569c64a520347f1cd85788dc1fb20d3b0a5c666e Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 26 Mar 2015 08:01:29 +0100 Subject: Updated Vagrant bootstrap file. --- vagrant/bootstrap.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vagrant/bootstrap.sh b/vagrant/bootstrap.sh index 1d931cf8..927a39b2 100644 --- a/vagrant/bootstrap.sh +++ b/vagrant/bootstrap.sh @@ -11,6 +11,9 @@ if [ $? -ne 0 ]; then exit 1; fi +# Installation of PostgreSQL +apt-get install -y postgresql postgresql-server-dev-9.4 postgresql-client + # Install all Python requierements cd pyaggr3g470r # For lxml @@ -25,9 +28,6 @@ sudo pip3 install feedparser==5.1.2 cp vagrant/conf.cfg-sample conf/conf.cfg cd .. -# Installation of PostgreSQL -apt-get install -y postgresql postgresql-server-dev-9.4 postgresql-client - # Configuration of the database echo "127.0.0.1:5432:aggregator:vagrant:xxYzToW42" > .pgpass chmod 700 .pgpass @@ -39,7 +39,8 @@ echo "GRANT ALL PRIVILEGES ON DATABASE aggregator TO vagrant;" | sudo -u postgre # Initializes the database cd pyaggr3g470r chown -R vagrant:vagrant . -sudo -u vagrant python3 db_create.py +sudo -u vagrant python3 manager.py db_empty +sudo -u vagrant python3 manager.py db_create # start pyAggr3g470r at startup echo "#!/bin/sh -e" > /etc/rc.local -- cgit From c2322d00e6842e7088f9452126234a2471c95f52 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 26 Mar 2015 09:09:55 +0100 Subject: Fixed configuration file for Vagrant. --- vagrant/conf.cfg-sample | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vagrant/conf.cfg-sample b/vagrant/conf.cfg-sample index 93a0b89c..fa76caad 100644 --- a/vagrant/conf.cfg-sample +++ b/vagrant/conf.cfg-sample @@ -1,10 +1,11 @@ [misc] -platform_url = https://pyaggr3g470r.herokuapp.com/ +platform_url = http://127.0.0.1:5000/ admin_email = recaptcha_public_key = recaptcha_private_key = log_path = ./pyaggr3g470r/var/pyaggr3g470r.log python = python3 +nb_worker = 5 [database] uri = postgres://vagrant:xxYzToW42@127.0.0.1:5432/aggregator [feedparser] -- cgit From 818e9b8b5386ec7cdc9397ec4b59e7aece62f1c1 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 26 Mar 2015 19:10:24 +0100 Subject: Updated Vagrant version. --- documentation/deployment.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/deployment.rst b/documentation/deployment.rst index 0402afd3..59080b89 100644 --- a/documentation/deployment.rst +++ b/documentation/deployment.rst @@ -14,8 +14,8 @@ Installation of VirtualBox and Vagrant .. code-block:: bash $ sudo apt-get install virtualbox - $ wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.6.5_x86_64.deb - $ sudo dpkg -i vagrant_1.6.5_x86_64.deb + $ wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_x86_64.deb + $ sudo dpkg -i vagrant_1.7.2_x86_64.deb Deployment of pyAggr3g470r -- cgit From 2b43c5da73ff8daa1b7b6b32f500cf9e502431c6 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 26 Mar 2015 21:16:29 +0100 Subject: Don't ask for confirmation of uninstall deletions with pip. --- vagrant/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vagrant/bootstrap.sh b/vagrant/bootstrap.sh index 927a39b2..6952afc3 100644 --- a/vagrant/bootstrap.sh +++ b/vagrant/bootstrap.sh @@ -22,7 +22,7 @@ apt-get install -y libxml2-dev libxslt1-dev sudo pip3 install --upgrade -r requirements.txt wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py sudo python3 get-pip.py -sudo pip3 uninstall feedparser +sudo pip3 uninstall -y feedparser sudo pip3 install feedparser==5.1.2 # copy of the default configuration files for vagrant cp vagrant/conf.cfg-sample conf/conf.cfg -- cgit From 7d94362fdde9a93b234be7a8be33a6ff819fe293 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Fri, 27 Mar 2015 06:58:24 +0100 Subject: Display the article id in the 'duplicates' page. --- pyaggr3g470r/templates/duplicates.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyaggr3g470r/templates/duplicates.html b/pyaggr3g470r/templates/duplicates.html index a7eff2d0..2c08306a 100644 --- a/pyaggr3g470r/templates/duplicates.html +++ b/pyaggr3g470r/templates/duplicates.html @@ -16,8 +16,8 @@ {% for pair in duplicates %} {{ loop.index }} -  {{ pair[0].title }} -  {{ pair[1].title }} +  {{ pair[0].title }} ({{ pair[0].entry_id }}) +  {{ pair[1].title }} ({{ pair[1].entry_id }}) {% endfor %} -- cgit From d1cbb124997166292eed2f7cfb25c82d82792226 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 09:55:16 +0100 Subject: It is now possible to delete all duplicate articles with one request. --- pyaggr3g470r/static/js/articles.js | 33 ++++++++++++++++++++++++++++++++- pyaggr3g470r/templates/duplicates.html | 8 ++++---- pyaggr3g470r/views/api/common.py | 3 ++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/pyaggr3g470r/static/js/articles.js b/pyaggr3g470r/static/js/articles.js index e30c6979..a5ac82d0 100644 --- a/pyaggr3g470r/static/js/articles.js +++ b/pyaggr3g470r/static/js/articles.js @@ -131,7 +131,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Requires jQuery') } var article_id = $(this).parent().parent().parent().attr("data-article"); $(this).parent().parent().parent().remove(); - // sends the updates to the server + // sends the updates to the server $.ajax({ type: 'DELETE', url: API_ROOT + "article/" + article_id, @@ -144,4 +144,35 @@ if (typeof jQuery === 'undefined') { throw new Error('Requires jQuery') } }); }); + + // Delete all duplicate articles (used in the page /duplicates) + $('.delete-all').click(function(){ + var data = []; + + var columnNo = $(this).parent().index(); + $(this).closest("table") + .find("tr td:nth-child(" + (columnNo+1) + ")") + .each(function(line, column) { + data.push(parseInt(column.id)); + }).remove(); + + data = JSON.stringify(data); + + // sends the updates to the server + $.ajax({ + type: 'DELETE', + // Provide correct Content-Type, so that Flask will know how to process it. + contentType: 'application/json', + data: data, + url: API_ROOT + "articles", + success: function (result) { + //console.log(result); + }, + error: function(XMLHttpRequest, textStatus, errorThrown){ + console.log(XMLHttpRequest.responseText); + } + }); + + }); + }(jQuery); diff --git a/pyaggr3g470r/templates/duplicates.html b/pyaggr3g470r/templates/duplicates.html index 2c08306a..2c953fa3 100644 --- a/pyaggr3g470r/templates/duplicates.html +++ b/pyaggr3g470r/templates/duplicates.html @@ -8,16 +8,16 @@ # - - + Delete all + Delete all {% for pair in duplicates %} {{ loop.index }} -  {{ pair[0].title }} ({{ pair[0].entry_id }}) -  {{ pair[1].title }} ({{ pair[1].entry_id }}) +  {{ pair[0].title }} ({{ pair[0].entry_id }}) +  {{ pair[1].title }} ({{ pair[1].entry_id }}) {% endfor %} diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index b1b0cd73..424df960 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -205,7 +205,8 @@ class PyAggResourceMulti(PyAggAbstractResource): def delete(self): """will delete several objects, a list of their ids should be in the payload""" - if 'application/json' != request.headers.get('Content-Type'): + if 'application/json' not in request.headers.get('Content-Type'): + print(request.headers.get('Content-Type')) raise BadRequest("Content-Type must be application/json") status = 204 results = [] -- cgit From a7df1043c338ea106cb745abcec70a3ce4e879a1 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 10:22:57 +0100 Subject: Test of the headers was to strict. --- pyaggr3g470r/views/api/common.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index 424df960..405d6b2c 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -149,7 +149,7 @@ class PyAggResourceMulti(PyAggAbstractResource): """retrieve several objects. filters can be set in the payload on the different fields of the object, and a limit can be set in there as well """ - if 'application/json' != request.headers.get('Content-Type'): + if 'application/json' not in request.headers.get('Content-Type'): raise BadRequest("Content-Type must be application/json") limit = 10 try: @@ -163,7 +163,7 @@ class PyAggResourceMulti(PyAggAbstractResource): def post(self): """creating several objects. payload should be a list of dict. """ - if 'application/json' != request.headers.get('Content-Type'): + if 'application/json' not int request.headers.get('Content-Type'): raise BadRequest("Content-Type must be application/json") status = 201 results = [] @@ -184,7 +184,7 @@ class PyAggResourceMulti(PyAggAbstractResource): [[obj_id1, {attr1: val1, attr2: val2}] [obj_id2, {attr1: val1, attr2: val2}]] """ - if 'application/json' != request.headers.get('Content-Type'): + if 'application/json' not in request.headers.get('Content-Type'): raise BadRequest("Content-Type must be application/json") status = 200 results = [] @@ -206,7 +206,6 @@ class PyAggResourceMulti(PyAggAbstractResource): """will delete several objects, a list of their ids should be in the payload""" if 'application/json' not in request.headers.get('Content-Type'): - print(request.headers.get('Content-Type')) raise BadRequest("Content-Type must be application/json") status = 204 results = [] -- cgit From 3bff51bc47e9c52de37773a2aad3c3682ab42704 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 10:26:34 +0100 Subject: Typo... --- pyaggr3g470r/views/api/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/views/api/common.py b/pyaggr3g470r/views/api/common.py index 405d6b2c..b8477d4b 100644 --- a/pyaggr3g470r/views/api/common.py +++ b/pyaggr3g470r/views/api/common.py @@ -163,7 +163,7 @@ class PyAggResourceMulti(PyAggAbstractResource): def post(self): """creating several objects. payload should be a list of dict. """ - if 'application/json' not int request.headers.get('Content-Type'): + if 'application/json' not in request.headers.get('Content-Type'): raise BadRequest("Content-Type must be application/json") status = 201 results = [] -- cgit From 687d985298957c3689547268928313a104bf6f89 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 11:23:47 +0100 Subject: Bugfix: unnecessary trailing slash. --- pyaggr3g470r/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index e88f5261..a7f8ad64 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -299,7 +299,7 @@ def tag_cloud(tags): Generates a tags cloud. """ tags.sort(key=operator.itemgetter(0)) - return '\n'.join([('%s' % \ + return '\n'.join([('%s' % \ (min(1 + count * 7 / max([tag[1] for tag in tags]), 7), word, format(count, ',d'), word)) \ for (word, count) in tags]) -- cgit From 21074e1b7a110d219d71049a8bae26f6b9466118 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 11:26:47 +0100 Subject: Improved table to the /duplicates page. --- pyaggr3g470r/templates/duplicates.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyaggr3g470r/templates/duplicates.html b/pyaggr3g470r/templates/duplicates.html index 2c953fa3..86990473 100644 --- a/pyaggr3g470r/templates/duplicates.html +++ b/pyaggr3g470r/templates/duplicates.html @@ -8,8 +8,12 @@ # - Delete all - Delete all + + {{ _('Delete all in this column') }} + + + {{ _('Delete all in this column') }} + -- cgit From fdc9f8fa076c00613c6ff156d0c1d46f02e38376 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 11:27:54 +0100 Subject: Updated translations. --- messages.pot | 13 +++++++++---- .../translations/fr/LC_MESSAGES/messages.mo | Bin 15486 -> 15562 bytes .../translations/fr/LC_MESSAGES/messages.po | 15 ++++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/messages.pot b/messages.pot index a8da28c1..a8bdf457 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-23 21:46+0100\n" +"POT-Creation-Date: 2015-03-28 11:26+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -211,8 +211,8 @@ msgid "from" msgstr "" #: pyaggr3g470r/templates/article.html:11 -#: pyaggr3g470r/templates/duplicates.html:19 -#: pyaggr3g470r/templates/duplicates.html:20 +#: pyaggr3g470r/templates/duplicates.html:23 +#: pyaggr3g470r/templates/duplicates.html:24 #: pyaggr3g470r/templates/home.html:90 msgid "Delete this article" msgstr "" @@ -250,7 +250,12 @@ msgstr "" msgid "Duplicates in the feed" msgstr "" -#: pyaggr3g470r/templates/duplicates.html:27 +#: pyaggr3g470r/templates/duplicates.html:12 +#: pyaggr3g470r/templates/duplicates.html:15 +msgid "Delete all in this column" +msgstr "" + +#: pyaggr3g470r/templates/duplicates.html:31 msgid "No duplicates in the feed" msgstr "" diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo index 72a16eb2..6ecf87bd 100644 Binary files a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo and b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po index 8561a0d8..8a0a5ca8 100644 --- a/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po +++ b/pyaggr3g470r/translations/fr/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-03-23 21:46+0100\n" -"PO-Revision-Date: 2015-03-23 21:47+0100\n" +"POT-Creation-Date: 2015-03-28 11:26+0100\n" +"PO-Revision-Date: 2015-03-28 11:27+0100\n" "Last-Translator: Cédric Bonhomme \n" "Language-Team: fr \n" "Language: fr\n" @@ -230,8 +230,8 @@ msgid "from" msgstr "de" #: pyaggr3g470r/templates/article.html:11 -#: pyaggr3g470r/templates/duplicates.html:19 -#: pyaggr3g470r/templates/duplicates.html:20 +#: pyaggr3g470r/templates/duplicates.html:23 +#: pyaggr3g470r/templates/duplicates.html:24 #: pyaggr3g470r/templates/home.html:90 msgid "Delete this article" msgstr "Supprimer cet article" @@ -269,7 +269,12 @@ msgstr "Partager sur" msgid "Duplicates in the feed" msgstr "Doublons dans le flux" -#: pyaggr3g470r/templates/duplicates.html:27 +#: pyaggr3g470r/templates/duplicates.html:12 +#: pyaggr3g470r/templates/duplicates.html:15 +msgid "Delete all in this column" +msgstr "Supprimer tout dans cette colonne" + +#: pyaggr3g470r/templates/duplicates.html:31 msgid "No duplicates in the feed" msgstr "Pas de doublon dans ce flux" -- cgit From bb5a7e24baf072af366b013240cc9d63f997153c Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 14:16:45 +0100 Subject: Pairs of duplicates are sorted by retrieved date. --- pyaggr3g470r/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index a7f8ad64..d1e4759b 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -312,7 +312,10 @@ def compare_documents(feed): date1, date2 = pair[0].date, pair[1].date if clear_string(pair[0].title) == clear_string(pair[1].title) and \ (date1 - date2) < timedelta(days = 1): - duplicates.append(pair) + if pair[0].retrieved_date < pair[1].retrieved_date: + duplicates.append((pair[0], pair[1])) + else: + duplicates.append(((pair[1], pair[0])) return duplicates def search_feed(url): -- cgit From 1781835efa43eaf9bfc2cc135a8f693ee57135e7 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 14:18:52 +0100 Subject: Typo... --- pyaggr3g470r/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index d1e4759b..513913a1 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -315,7 +315,7 @@ def compare_documents(feed): if pair[0].retrieved_date < pair[1].retrieved_date: duplicates.append((pair[0], pair[1])) else: - duplicates.append(((pair[1], pair[0])) + duplicates.append((pair[1], pair[0])) return duplicates def search_feed(url): -- cgit From 341008ac376479468d68bb2fb1c9ce0cd82b10e8 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sat, 28 Mar 2015 14:37:23 +0100 Subject: Clean the file utils.py --- pyaggr3g470r/models/article.py | 2 +- pyaggr3g470r/utils.py | 96 +++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 58 deletions(-) diff --git a/pyaggr3g470r/models/article.py b/pyaggr3g470r/models/article.py index 0466bc35..f026984a 100644 --- a/pyaggr3g470r/models/article.py +++ b/pyaggr3g470r/models/article.py @@ -4,7 +4,7 @@ # pyAggr3g470r - A Web based news aggregator. # Copyright (C) 2010-2015 Cédric Bonhomme - https://www.cedricbonhomme.org # -# For more information : https://bitbucket.org/cedricbonhomme/pyaggr3g470r/ +# For more information : https://bitbucket.org/cedricbonhomme/pyaggr3g470r # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/pyaggr3g470r/utils.py b/pyaggr3g470r/utils.py index 513913a1..5f2d8707 100755 --- a/pyaggr3g470r/utils.py +++ b/pyaggr3g470r/utils.py @@ -4,7 +4,7 @@ # pyAggr3g470r - A Web based news aggregator. # Copyright (C) 2010-2015 Cédric Bonhomme - https://www.cedricbonhomme.org # -# For more information : https://bitbucket.org/cedricbonhomme/pyaggr3g470r/ +# For more information : https://bitbucket.org/cedricbonhomme/pyaggr3g470r # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -20,15 +20,16 @@ # along with this program. If not, see . __author__ = "Cedric Bonhomme" -__version__ = "$Revision: 1.6 $" +__version__ = "$Revision: 1.7 $" __date__ = "$Date: 2010/12/07 $" -__revision__ = "$Date: 2013/11/17 $" +__revision__ = "$Date: 2015/03/28 $" __copyright__ = "Copyright (c) Cedric Bonhomme" __license__ = "AGPLv3" # # This file provides functions used for: -# - the database management; +# - detection of duplicate articles; +# - import from a JSON file; # - generation of tags cloud; # - HTML processing. # @@ -58,18 +59,8 @@ from flask import g from pyaggr3g470r import controllers from pyaggr3g470r.models import User, Feed, Article - -# regular expression to check URL -url_finders = [ - re.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+)(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\),\\\"]"), \ - re.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+)(:[0-9]*)?"), \ - re.compile("(~/|/|\\./)([-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]|\\\\)+"), \ - re.compile("'\\<((mailto:)|)[-A-Za-z0-9\\.]+@[-A-Za-z0-9\\.]+") \ -] - logger = logging.getLogger(__name__) - @contextmanager def opened_w_error(filename, mode="r"): try: @@ -83,11 +74,17 @@ def opened_w_error(filename, mode="r"): f.close() def fetch(id, feed_id=None): - cmd = [conf.PYTHON, conf.basedir+'/manager.py', 'fetch_asyncio', str(id), str(feed_id)] + """ + Fetch the feeds in a new processus. + The "asyncio" crawler is launched with the manager. + """ + cmd = [conf.PYTHON, conf.basedir+'/manager.py', 'fetch_asyncio', str(id), + str(feed_id)] p = subprocess.Popen(cmd, stdout=subprocess.PIPE) def history(user_id, year=None, month=None): """ + Sort articles by year and month. """ articles_counter = Counter() articles = controllers.ArticleController(user_id).read() @@ -118,43 +115,33 @@ def import_opml(email, opml_content): Parse recursively through the categories and sub-categories. """ for subscription in subsubscription: - if len(subscription) != 0: nb = read(subscription, nb) else: - try: title = subscription.text - except: title = "" - try: description = subscription.description except: description = "" - try: link = subscription.xmlUrl except: continue - if None != Feed.query.filter(Feed.user_id == user.id, Feed.link == link).first(): continue - try: site_link = subscription.htmlUrl except: site_link = "" - new_feed = Feed(title=title, description=description, link=link, site_link=site_link, enabled=True) - user.feeds.append(new_feed) nb += 1 return nb - nb = read(subscriptions) g.db.session.commit() return nb @@ -166,44 +153,46 @@ def import_json(email, json_content): user = User.query.filter(User.email == email).first() json_account = json.loads(json_content) nb_feeds, nb_articles = 0, 0 - - # Create feeds + # Create feeds: for feed in json_account["result"]: - - if None != Feed.query.filter(Feed.user_id == user.id, Feed.link == feed["link"]).first(): + if None != Feed.query.filter(Feed.user_id == user.id, + Feed.link == feed["link"]).first(): continue - - new_feed = Feed(title=feed["title"], description="", link=feed["link"], \ - site_link=feed["site_link"], \ - created_date=datetime.datetime.fromtimestamp(int(feed["created_date"])), - enabled=feed["enabled"]) + new_feed = Feed(title=feed["title"], + description="", + link=feed["link"], + site_link=feed["site_link"], + created_date=datetime.datetime.\ + fromtimestamp(int(feed["created_date"])), + enabled=feed["enabled"]) user.feeds.append(new_feed) nb_feeds += 1 g.db.session.commit() - - # Create articles + # Create articles: for feed in json_account["result"]: - user_feed = Feed.query.filter(Feed.user_id == user.id, Feed.link == feed["link"]).first() + user_feed = Feed.query.filter(Feed.user_id == user.id, + Feed.link == feed["link"]).first() if None != user_feed: for article in feed["articles"]: - if None == Article.query.filter(Article.user_id == user.id, - Article.feed_id == user_feed.id, - Article.link == article["link"]).first(): - - new_article = Article(link=article["link"], title=article["title"], \ - content=article["content"], readed=article["readed"], like=article["like"], \ - retrieved_date=datetime.datetime.fromtimestamp(int(article["retrieved_date"])), - date=datetime.datetime.fromtimestamp(int(article["date"])), - user_id=user.id, feed_id=user_feed.id) - + Article.feed_id == user_feed.id, + Article.link == article["link"]).first(): + new_article = Article(link=article["link"], + title=article["title"], + content=article["content"], + readed=article["readed"], + like=article["like"], \ + retrieved_date=datetime.datetime.\ + fromtimestamp(int(article["retrieved_date"])), + date=datetime.datetime.\ + fromtimestamp(int(article["date"])), + user_id=user.id, + feed_id=user_feed.id) user_feed.articles.append(new_article) nb_articles += 1 g.db.session.commit() - return nb_feeds, nb_articles - def clean_url(url): """ Remove utm_* parameters @@ -221,7 +210,6 @@ def clean_url(url): parsed_url.fragment ]).rstrip('=') - def open_url(url): """ Open an URL with the proxy and the user-agent @@ -240,7 +228,6 @@ def open_url(url): # server couldn't fulfill the request error = (url, e.code, \ http.server.BaseHTTPRequestHandler.responses[e.code][1]) - #pyaggr3g470r_log.error(url + " " + str(e.code) + " " + http.server.BaseHTTPRequestHandler.responses[e.code][1]) return (False, error) except urllib.error.URLError as e: # failed to reach the server @@ -249,10 +236,8 @@ def open_url(url): #pyaggr3g470r_log.error(url + " " + e.reason) else: error = (url, e.reason.errno, e.reason.strerror) - #pyaggr3g470r_log.error(url + " " + str(e.reason.errno) + " " + e.reason.strerror) return (False, error) - def clear_string(data): """ Clear a string by removing HTML tags, HTML special caracters @@ -262,7 +247,6 @@ def clear_string(data): q = re.compile('\s') # consecutive white spaces return p.sub('', q.sub(' ', data)) - def load_stop_words(): """ Load the stop words and return them in a list. @@ -278,7 +262,6 @@ def load_stop_words(): stop_words += stop_wods_file.read().split(";") return stop_words - def top_words(articles, n=10, size=5): """ Return the n most frequent words in a list. @@ -293,7 +276,6 @@ def top_words(articles, n=10, size=5): words[word] += 1 return words.most_common(n) - def tag_cloud(tags): """ Generates a tags cloud. @@ -306,6 +288,7 @@ def tag_cloud(tags): def compare_documents(feed): """ Compare a list of documents by pair. + Pairs of duplicates are sorted by "retrieved date". """ duplicates = [] for pair in itertools.combinations(feed.articles, 2): @@ -340,7 +323,6 @@ def search_feed(url): return feed_link['href'] return None - if __name__ == "__main__": import_opml("root@pyAggr3g470r.localhost", "./var/feeds_test.opml") #import_opml("root@pyAggr3g470r.localhost", "./var/pyAggr3g470r.opml") -- cgit From 3de4282a367b758d8bfcdfbfdd1cb995c283f213 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 29 Mar 2015 00:08:01 +0100 Subject: Use more the controllers in views.py. user_id_key is the email. --- pyaggr3g470r/controllers/user.py | 2 +- pyaggr3g470r/views/views.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pyaggr3g470r/controllers/user.py b/pyaggr3g470r/controllers/user.py index c6c1d545..ed46e1e7 100644 --- a/pyaggr3g470r/controllers/user.py +++ b/pyaggr3g470r/controllers/user.py @@ -4,4 +4,4 @@ from pyaggr3g470r.models import User class UserController(AbstractController): _db_cls = User - _user_id_key = 'id' + _user_id_key = 'email' diff --git a/pyaggr3g470r/views/views.py b/pyaggr3g470r/views/views.py index dc6bfead..f77bdeba 100644 --- a/pyaggr3g470r/views/views.py +++ b/pyaggr3g470r/views/views.py @@ -47,6 +47,7 @@ from werkzeug import generate_password_hash import conf from pyaggr3g470r import utils, notifications, export +from pyaggr3g470r import controllers from pyaggr3g470r.models import User, Feed, Article, Role from pyaggr3g470r.decorators import feed_access_required from pyaggr3g470r.forms import SignupForm, SigninForm, AddFeedForm, \ @@ -92,7 +93,7 @@ def before_request(): @login_manager.user_loader def load_user(email): # Return an instance of the User model - return User.query.filter(User.email == email).first() + return controllers.UserController(email).get(email=email) # @@ -152,7 +153,7 @@ def login(): form = SigninForm() if form.validate_on_submit(): - user = User.query.filter(User.email == form.email.data).first() + user = controllers.UserController(form.email.data).get(email=form.email.data) login_user(user) g.user = user session['email'] = form.email.data @@ -381,7 +382,7 @@ def inactives(): List of inactive feeds. """ nb_days = int(request.args.get('nb_days', 365)) - user = User.query.filter(User.id == g.user.id).first() + user = controllers.UserController(g.user.email).get(email=g.user.email) today = datetime.datetime.now() inactives = [] for feed in user.feeds: @@ -428,7 +429,7 @@ def export_articles(): """ Export all articles to HTML or JSON. """ - user = User.query.filter(User.id == g.user.id).first() + user = controllers.UserController(g.user.email).get(id=g.user.id) if request.args.get('format') == "HTML": # Export to HTML try: @@ -460,7 +461,7 @@ def export_opml(): """ Export all feeds to OPML. """ - user = User.query.filter(User.id == g.user.id).first() + user = controllers.UserController(g.user.email).get(id=g.user.id) response = make_response(render_template('opml.xml', user=user, now=datetime.datetime.now())) response.headers['Content-Type'] = 'application/xml' response.headers['Content-Disposition'] = 'attachment; filename=feeds.opml' @@ -636,7 +637,7 @@ def profile(): """ Edit the profile of the currently logged user. """ - user = User.query.filter(User.email == g.user.email).first() + user = controllers.UserController(g.user.email).get(id=g.user.id) form = ProfileForm() if request.method == 'POST': @@ -662,7 +663,7 @@ def delete_account(): """ Delete the account of the user (with all its data). """ - user = User.query.filter(User.email == g.user.email).first() + user = controllers.UserController(g.user.email).get(id=g.user.id) if user is not None: db.session.delete(user) db.session.commit() -- cgit From 20677d77dec1d06703b12b4e6f0a4aa551a687ee Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Sun, 29 Mar 2015 10:59:59 +0200 Subject: Displays the 'retrieved_date' instead of the 'id' in the /duplicates page. --- pyaggr3g470r/templates/duplicates.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyaggr3g470r/templates/duplicates.html b/pyaggr3g470r/templates/duplicates.html index 86990473..4d7ac650 100644 --- a/pyaggr3g470r/templates/duplicates.html +++ b/pyaggr3g470r/templates/duplicates.html @@ -20,8 +20,8 @@ {% for pair in duplicates %} {{ loop.index }} -  {{ pair[0].title }} ({{ pair[0].entry_id }}) -  {{ pair[1].title }} ({{ pair[1].entry_id }}) +  {{ pair[0].title }} ({{ pair[0].retrieved_date }}) +  {{ pair[1].title }} ({{ pair[1].retrieved_date }}) {% endfor %} -- cgit From 8abb94bb5f915b778624b7185545b26c747430a4 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Mon, 30 Mar 2015 14:13:32 +0200 Subject: Create a cron job at the end of the bootstraping of Vagrant. --- vagrant/bootstrap.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vagrant/bootstrap.sh b/vagrant/bootstrap.sh index 6952afc3..1361f69b 100644 --- a/vagrant/bootstrap.sh +++ b/vagrant/bootstrap.sh @@ -51,3 +51,12 @@ chmod 755 /etc/rc.local # Start the application. /etc/init.d/rc.local start + + +#write out current crontab +sudo -u vagrant crontab -l > mycron +#echo new cron into cron file +sudo -u vagrant echo "*/30 * * * * cd /home/vagrant/pyaggr3g470r/ ; python3 manager.py fetch_asyncio None None" >> mycron +#install new cron file +sudo -u vagrant crontab mycron +sudo -u vagrant rm mycron -- cgit From 3f760d8ad4da06e264e517d0671a6616376448ad Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Tue, 31 Mar 2015 08:44:17 +0200 Subject: Clean the directory when installing pyAggr3g470r with Vagrant. --- vagrant/bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/vagrant/bootstrap.sh b/vagrant/bootstrap.sh index 1361f69b..62747f64 100644 --- a/vagrant/bootstrap.sh +++ b/vagrant/bootstrap.sh @@ -22,6 +22,7 @@ apt-get install -y libxml2-dev libxslt1-dev sudo pip3 install --upgrade -r requirements.txt wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py sudo python3 get-pip.py +rm get-pip.py sudo pip3 uninstall -y feedparser sudo pip3 install feedparser==5.1.2 # copy of the default configuration files for vagrant -- cgit From d987c309ca583b3682d1d8c97f2985f5d5876af9 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 1 Apr 2015 21:57:44 +0200 Subject: Added customized-bootstrap.css file. --- pyaggr3g470r/static/css/customized-bootstrap.css | 34 ++++++++++++++++++++++++ pyaggr3g470r/templates/layout.html | 7 ++--- 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 pyaggr3g470r/static/css/customized-bootstrap.css diff --git a/pyaggr3g470r/static/css/customized-bootstrap.css b/pyaggr3g470r/static/css/customized-bootstrap.css new file mode 100644 index 00000000..b8222548 --- /dev/null +++ b/pyaggr3g470r/static/css/customized-bootstrap.css @@ -0,0 +1,34 @@ +.navbar-custom { + background-color: #205081; + border: #205081; + color: #FFFFFF; + border-radius: 0; +} + +.navbar-custom .navbar-nav > li > a { + color: #FFFFFF; +} + +.navbar-custom .navbar-nav > li > a:hover { + background-color: #3572B0; +} + +.navbar-custom .navbar-nav > .active > a, +.navbar-nav > .active > a:hover, +.navbar-nav > .active > a:focus { + color: #FFFFFF; + background-color: #3572B0; +} +.navbar-custom .navbar-brand { + color: #FFFFFF; +} + +.navbar-custom .navbar-nav > .open > a, +.navbar-custom .navbar-nav > .open > a:hover, +.navbar-custom .navbar-nav > .open > a:focus { + color: #FFFFFF; + background-color: #3572B0; +} +a { + color: #3572B0; +} diff --git a/pyaggr3g470r/templates/layout.html b/pyaggr3g470r/templates/layout.html index 6b929bf3..12c02814 100644 --- a/pyaggr3g470r/templates/layout.html +++ b/pyaggr3g470r/templates/layout.html @@ -10,6 +10,7 @@ + {% endblock %} - -
    - +
    {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} -- cgit