From cb6a8d8b53bb27755eb9bc040f86a361636d4c6a Mon Sep 17 00:00:00 2001 From: François Schmidts Date: Sun, 8 Jun 2014 17:47:42 +0200 Subject: adding the capacity to mark articles as unread --- pyaggr3g470r/templates/article.html | 1 + pyaggr3g470r/templates/home.html | 5 +++-- pyaggr3g470r/templates/layout.html | 4 ++-- pyaggr3g470r/templates/unread.html | 3 ++- pyaggr3g470r/views.py | 26 +++++++++++++++++--------- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/pyaggr3g470r/templates/article.html b/pyaggr3g470r/templates/article.html index 83e23b34..1ee86948 100644 --- a/pyaggr3g470r/templates/article.html +++ b/pyaggr3g470r/templates/article.html @@ -14,6 +14,7 @@ {% else %} {% endif %} +
{{ article.date | datetime }}
diff --git a/pyaggr3g470r/templates/home.html b/pyaggr3g470r/templates/home.html index c1663997..297e0214 100644 --- a/pyaggr3g470r/templates/home.html +++ b/pyaggr3g470r/templates/home.html @@ -25,7 +25,7 @@

{{ feed.title|safe }} {% if feed.nb_unread != 0 %} - {{ feed.nb_unread }} + {{ feed.nb_unread }} {% endif %}

@@ -34,8 +34,9 @@ {% endif %} {% if feed.nb_unread != 0 %} - + {% endif %} +
{% for number in range(0, feed.articles.all()|count-(feed.articles.all()|count % 3), 3) %} diff --git a/pyaggr3g470r/templates/layout.html b/pyaggr3g470r/templates/layout.html index d1040422..8fc88d74 100644 --- a/pyaggr3g470r/templates/layout.html +++ b/pyaggr3g470r/templates/layout.html @@ -27,7 +27,7 @@ deployed on Heroku or on a traditional server." /> height: 0; } ul.affix { - position: fixed; + position: fixed; top: 0px; } ul.affix-top { @@ -102,7 +102,7 @@ deployed on Heroku or on a traditional server." /> {{ _('Articles') }} diff --git a/pyaggr3g470r/templates/unread.html b/pyaggr3g470r/templates/unread.html index 6c5c5d08..cdfb0dfe 100644 --- a/pyaggr3g470r/templates/unread.html +++ b/pyaggr3g470r/templates/unread.html @@ -16,7 +16,8 @@ - + +

{{ feed.articles.all()|length }} {{ _('unread articles') }}.

diff --git a/pyaggr3g470r/views.py b/pyaggr3g470r/views.py index e4668f54..1f3e16d7 100644 --- a/pyaggr3g470r/views.py +++ b/pyaggr3g470r/views.py @@ -312,23 +312,31 @@ def article(article_id=None): return redirect(redirect_url()) -@app.route('/mark_as_read/', methods=['GET']) -@app.route('/mark_as_read/', methods=['GET']) +@app.route('/mark_as/', methods=['GET']) +@app.route('/mark_as//feed/', methods=['GET']) +@app.route('/mark_as//article/', methods=['GET']) @login_required @feed_access_required -def mark_as_read(feed_id=None): +def mark_as(new_value='read', feed_id=None, article_id=None): """ Mark all unreaded articles as read. """ + readed = new_value == 'read' + articles = Article.query.filter(Article.user_id == g.user.id) if feed_id is not None: - Article.query.filter(Article.user_id == g.user.id, Article.feed_id == feed_id, - Article.readed == False).update({"readed": True}) - flash(gettext('Articles marked as read.'), 'info') + articles = articles.filter(Article.feed_id == feed_id) + message = 'Feed marked as %s.' + elif article_id is not None: + articles = articles.filter(Article.id == article_id) + message = 'Article marked as %s.' else: - Article.query.filter(Article.user_id == g.user.id, Article.readed == False).update({"readed": True}) - flash(gettext("All articles marked as read"), 'info') + message = 'All article marked as %s.' + articles.filter(Article.readed == (not readed)).update({"readed": readed}) + flash(gettext(message % new_value), 'info') db.session.commit() - return redirect(redirect_url()) + if readed: + return redirect(redirect_url()) + return redirect('/#%d' % articles.first().feed_id) @app.route('/like/', methods=['GET']) @login_required -- cgit From 9731e3604fe360f662a042f3249bb39ddec6adf5 Mon Sep 17 00:00:00 2001 From: François Schmidts Date: Wed, 11 Jun 2014 23:55:06 +0200 Subject: redoing home page --- pyaggr3g470r/static/css/bootstrap.css | 6 +++ pyaggr3g470r/templates/article.html | 16 +++++-- pyaggr3g470r/templates/home.html | 71 ---------------------------- pyaggr3g470r/templates/reader.html | 88 +++++++++++++++++++++++++++++++++++ pyaggr3g470r/views.py | 61 +++++++++++++++--------- 5 files changed, 145 insertions(+), 97 deletions(-) delete mode 100644 pyaggr3g470r/templates/home.html create mode 100644 pyaggr3g470r/templates/reader.html diff --git a/pyaggr3g470r/static/css/bootstrap.css b/pyaggr3g470r/static/css/bootstrap.css index 14cc1f48..0b9217fc 100644 --- a/pyaggr3g470r/static/css/bootstrap.css +++ b/pyaggr3g470r/static/css/bootstrap.css @@ -5829,3 +5829,9 @@ td.visible-print { } } /*# sourceMappingURL=bootstrap.css.map */ +.strict-table td{ + min-width: 70px; +} +.strict-table td.date { + min-width: 190px; +} diff --git a/pyaggr3g470r/templates/article.html b/pyaggr3g470r/templates/article.html index 1ee86948..2dbdb8de 100644 --- a/pyaggr3g470r/templates/article.html +++ b/pyaggr3g470r/templates/article.html @@ -9,12 +9,18 @@

{{ article.title|safe }}

{{ _('from') }} {{ article.source.title }}

- {% if article.like %} - - {% else %} - + + {% if article.like %} + + {% else %} + + {% endif %} + + {% if article.readed %} + + {% else %} + {% endif %} -
{{ article.date | datetime }}
diff --git a/pyaggr3g470r/templates/home.html b/pyaggr3g470r/templates/home.html deleted file mode 100644 index 297e0214..00000000 --- a/pyaggr3g470r/templates/home.html +++ /dev/null @@ -1,71 +0,0 @@ - {% extends "layout.html" %} -{% block content %} -
-
- -
- {% if result|count == 0 %} -

{{ _("You don't have any feeds.") }}

-

{{ _('Add some') }}, {{ _('or') }} {{ _('upload an OPML file.') }}

- {% else %} - {% for feed in result|sort(attribute="title") %} -
-
-
-

{{ feed.title|safe }} - {% if feed.nb_unread != 0 %} - {{ feed.nb_unread }} - {% endif %}

- - - - {% if feed.enabled %} - - {% endif %} - {% if feed.nb_unread != 0 %} - - {% endif %} - -
-
- {% for number in range(0, feed.articles.all()|count-(feed.articles.all()|count % 3), 3) %} -
- {% for n in range(number, number+3) %} -
- {% if feed.articles[n].readed %}

{% else %}

{% endif %} - {{ feed.articles[n].title|safe }} - {% if feed.articles[n].readed %}

{% else %}{% endif %} -
{{ feed.articles[n].date | datetime }}
-
- {% endfor %} -
- {% endfor %} - {% if feed.articles.all()|count % 3 != 0 %} -
- {% for n in range(feed.articles.all()|count-(feed.articles.all()|count % 3), feed.articles.all()|count) %} -
- {% if feed.articles[n].readed %}

{% else %}

{% endif %} - {{ feed.articles[n].title|safe }} - {% if feed.articles[n].readed %}

{% else %}{% endif %} -
{{ feed.articles[n].date | datetime }}
-
- {% endfor %} -
- {% endif %} - {% endfor %} - {% endif %} -
-
-
-{% endblock %} diff --git a/pyaggr3g470r/templates/reader.html b/pyaggr3g470r/templates/reader.html new file mode 100644 index 00000000..a2b4481c --- /dev/null +++ b/pyaggr3g470r/templates/reader.html @@ -0,0 +1,88 @@ +{% extends "layout.html" %} +{% block content %} + +
+

{{ _('Your articles') }} ({{ articles.__len__() }})

+
+ {% if filter_ == 'all' %}{% endif %} + {{ _('All') }} + {% if filter_ == 'all' %}{% endif %} + | + {% if filter_ == 'read' %}{% endif %} + {{ _('Read') }} + {% if filter_ == 'read' %}{% endif %} + | + {% if filter_ == 'unread' %}{% endif %} + {{ _('Unread') }} + {% if filter_ == 'unread' %}{% endif %} + - + {% if limit == 10 %}{% endif %} + {{ _(10) }} + {% if limit == 10 %}{% endif %} + | + {% if limit == 100 %}{% endif %} + {{ _(100) }} + {% if limit == 100 %}{% endif %} + | + {% if limit == 1000 %}{% endif %} + {{ _(1000) }} + {% if limit == 1000 %}{% endif %} + | + {% if limit == 'all' %}{% endif %} + {{ _('All') }} + {% if limit == 'all' %}{% endif %} + +
+
+ + + + + + + + + + + {% for article in articles %} + + + + + + + {% endfor %} + +
{{ _('Feed') }}{{ _('Article') }}{{ _('Date') }}
{{ article.source.title|safe }}{{ article.title|safe }}{{ article.date|datetime }} + + + {% if article.like %} + + {% else %} + + {% endif %} + + {% if article.readed %} + + {% else %} + + {% endif %} +
+
+
+{% endblock %} diff --git a/pyaggr3g470r/views.py b/pyaggr3g470r/views.py index 1f3e16d7..2ad1ea5a 100644 --- a/pyaggr3g470r/views.py +++ b/pyaggr3g470r/views.py @@ -28,9 +28,13 @@ __license__ = "AGPLv3" import os import datetime -from flask import render_template, request, flash, session, url_for, redirect, g, current_app, make_response -from flask.ext.login import LoginManager, login_user, logout_user, login_required, current_user, AnonymousUserMixin -from flask.ext.principal import Principal, Identity, AnonymousIdentity, identity_changed, identity_loaded, Permission, RoleNeed, UserNeed +from flask import abort, render_template, request, flash, session, \ + url_for, redirect, g, current_app, make_response +from flask.ext.login import LoginManager, login_user, logout_user, \ + login_required, current_user, AnonymousUserMixin +from flask.ext.principal import Principal, Identity, AnonymousIdentity, \ + identity_changed, identity_loaded, Permission,\ + RoleNeed, UserNeed from flask.ext.babel import gettext from sqlalchemy import desc from sqlalchemy.exc import IntegrityError @@ -209,23 +213,38 @@ def signup(): @app.route('/') @login_required def home(): - """ - The home page lists most recent articles of all feeds. - """ - #user = User.query.filter(User.email == g.user.email).first() - result = [] - for feed in g.user.feeds: - new_feed = Feed() - new_feed.id = feed.id - new_feed.title = feed.title - new_feed.enabled = feed.enabled - new_feed.articles = feed.articles[:9] - #new_feed.articles = Article.query.filter(Article.user_id == g.user.id, - #Article.feed_id == feed.id).order_by(desc("Article.date")).limit(9) - new_feed.nb_unread = Article.query.filter(Article.user_id == g.user.id, Article.feed_id == feed.id, Article.readed == False).count() - result.append(new_feed) - unread_articles = len(Article.query.filter(Article.user_id == g.user.id, Article.readed == False).all()) - return render_template('home.html', result=result, head_title=unread_articles) + feeds = {feed.id: feed.title for feed in g.user.feeds if feed.enabled} + articles = Article.query.filter(Article.feed_id.in_(feeds.keys())) + filter_ = request.args.get('filter_', 'unread') + feed_id = int(request.args.get('feed', 0)) + limit = request.args.get('limit', 1000) + if filter_ != 'all': + articles = articles.filter(Article.readed == (filter_ == 'read')) + if feed_id: + articles = articles.filter(Article.feed_id == feed_id) + + articles = articles.order_by(Article.date.desc()) + if limit != 'all': + limit = int(limit) + articles = articles.limit(limit) + def gen_url(filter_=filter_, limit=limit, feed=feed_id): + return '/?filter_=%s&limit=%s&feed=%d' % (filter_, limit, feed) + return render_template('reader.html', gen_url=gen_url, feed_id=feed_id, + filter_=filter_, limit=limit, feeds=feeds, + articles=articles.all()) + + +@app.route('/article/redirect/', methods=['GET']) +@login_required +def redirect_to_article(article_id): + article = Article.query.filter(Article.id == article_id, + Article.user_id == g.user.id).first() + if article is None: + abort(404) + article.readed = True + db.session.commit() + return redirect(article.link) + @app.route('/fetch/', methods=['GET']) @app.route('/fetch/', methods=['GET']) @@ -336,7 +355,7 @@ def mark_as(new_value='read', feed_id=None, article_id=None): db.session.commit() if readed: return redirect(redirect_url()) - return redirect('/#%d' % articles.first().feed_id) + return redirect(redirect_url()) @app.route('/like/', methods=['GET']) @login_required -- cgit From 7c066abd8a706ec9027d7c43f0b185e57a0951a0 Mon Sep 17 00:00:00 2001 From: François Schmidts Date: Thu, 12 Jun 2014 01:16:45 +0200 Subject: aligning message box to the right --- pyaggr3g470r/templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaggr3g470r/templates/layout.html b/pyaggr3g470r/templates/layout.html index 8fc88d74..543fc823 100644 --- a/pyaggr3g470r/templates/layout.html +++ b/pyaggr3g470r/templates/layout.html @@ -145,7 +145,7 @@ deployed on Heroku or on a traditional server." />
-
+
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} -- cgit From 189daeb5862dcf6d89e5070c019cd584c26e73a6 Mon Sep 17 00:00:00 2001 From: François Schmidts Date: Thu, 12 Jun 2014 01:50:08 +0200 Subject: reimplementing the unread count in left menu --- pyaggr3g470r/templates/home.html | 96 ++++++++++++++++++++++++++++++++++++++ pyaggr3g470r/templates/reader.html | 88 ---------------------------------- pyaggr3g470r/views.py | 9 ++-- 3 files changed, 102 insertions(+), 91 deletions(-) create mode 100644 pyaggr3g470r/templates/home.html delete mode 100644 pyaggr3g470r/templates/reader.html diff --git a/pyaggr3g470r/templates/home.html b/pyaggr3g470r/templates/home.html new file mode 100644 index 00000000..96cd83a5 --- /dev/null +++ b/pyaggr3g470r/templates/home.html @@ -0,0 +1,96 @@ +{% extends "layout.html" %} +{% block content %} + +
+

{{ _('Your articles') }} ({{ articles.__len__() }})

+
+ {% if filter_ == 'all' %}{% endif %} + {{ _('All') }} + {% if filter_ == 'all' %}{% endif %} + | + {% if filter_ == 'read' %}{% endif %} + {{ _('Read') }} + {% if filter_ == 'read' %}{% endif %} + | + {% if filter_ == 'unread' %}{% endif %} + {{ _('Unread') }} + {% if filter_ == 'unread' %}{% endif %} + - + {% if limit == 10 %}{% endif %} + {{ _(10) }} + {% if limit == 10 %}{% endif %} + | + {% if limit == 100 %}{% endif %} + {{ _(100) }} + {% if limit == 100 %}{% endif %} + | + {% if limit == 1000 %}{% endif %} + {{ _(1000) }} + {% if limit == 1000 %}{% endif %} + | + {% if limit == 'all' %}{% endif %} + {{ _('All') }} + {% if limit == 'all' %}{% endif %} + +
+
+ + + + + + + + + + + {% for article in articles %} + + + + + + + {% endfor %} + +
{{ _('Feed') }}{{ _('Article') }}{{ _('Date') }}
{{ article.source.title|safe }}{{ article.title|safe }}{{ article.date|datetime }} + + + {% if article.like %} + + {% else %} + + {% endif %} + + {% if article.readed %} + + {% else %} + + {% endif %} +
+
+
+{% endblock %} diff --git a/pyaggr3g470r/templates/reader.html b/pyaggr3g470r/templates/reader.html deleted file mode 100644 index a2b4481c..00000000 --- a/pyaggr3g470r/templates/reader.html +++ /dev/null @@ -1,88 +0,0 @@ -{% extends "layout.html" %} -{% block content %} - -
-

{{ _('Your articles') }} ({{ articles.__len__() }})

-
- {% if filter_ == 'all' %}{% endif %} - {{ _('All') }} - {% if filter_ == 'all' %}{% endif %} - | - {% if filter_ == 'read' %}{% endif %} - {{ _('Read') }} - {% if filter_ == 'read' %}{% endif %} - | - {% if filter_ == 'unread' %}{% endif %} - {{ _('Unread') }} - {% if filter_ == 'unread' %}{% endif %} - - - {% if limit == 10 %}{% endif %} - {{ _(10) }} - {% if limit == 10 %}{% endif %} - | - {% if limit == 100 %}{% endif %} - {{ _(100) }} - {% if limit == 100 %}{% endif %} - | - {% if limit == 1000 %}{% endif %} - {{ _(1000) }} - {% if limit == 1000 %}{% endif %} - | - {% if limit == 'all' %}{% endif %} - {{ _('All') }} - {% if limit == 'all' %}{% endif %} - -
-
- - - - - - - - - - - {% for article in articles %} - - - - - - - {% endfor %} - -
{{ _('Feed') }}{{ _('Article') }}{{ _('Date') }}
{{ article.source.title|safe }}{{ article.title|safe }}{{ article.date|datetime }} - - - {% if article.like %} - - {% else %} - - {% endif %} - - {% if article.readed %} - - {% else %} - - {% endif %} -
-
-
-{% endblock %} diff --git a/pyaggr3g470r/views.py b/pyaggr3g470r/views.py index 2ad1ea5a..1b3be75e 100644 --- a/pyaggr3g470r/views.py +++ b/pyaggr3g470r/views.py @@ -36,7 +36,7 @@ from flask.ext.principal import Principal, Identity, AnonymousIdentity, \ identity_changed, identity_loaded, Permission,\ RoleNeed, UserNeed from flask.ext.babel import gettext -from sqlalchemy import desc +from sqlalchemy import desc, func from sqlalchemy.exc import IntegrityError from werkzeug import generate_password_hash @@ -227,11 +227,14 @@ def home(): if limit != 'all': limit = int(limit) articles = articles.limit(limit) + unread = db.session.query(Article.feed_id, func.count(Article.id))\ + .filter(Article.readed == False)\ + .group_by(Article.feed_id).all() def gen_url(filter_=filter_, limit=limit, feed=feed_id): return '/?filter_=%s&limit=%s&feed=%d' % (filter_, limit, feed) - return render_template('reader.html', gen_url=gen_url, feed_id=feed_id, + return render_template('home.html', gen_url=gen_url, feed_id=feed_id, filter_=filter_, limit=limit, feeds=feeds, - articles=articles.all()) + unread=dict(unread), articles=articles.all()) @app.route('/article/redirect/', methods=['GET']) -- cgit