aboutsummaryrefslogtreecommitdiff
path: root/src/web/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/views')
-rw-r--r--src/web/views/article.py81
-rw-r--r--src/web/views/feed.py26
-rw-r--r--src/web/views/views.py117
3 files changed, 110 insertions, 114 deletions
diff --git a/src/web/views/article.py b/src/web/views/article.py
index bb914a6b..d308d37e 100644
--- a/src/web/views/article.py
+++ b/src/web/views/article.py
@@ -1,31 +1,32 @@
#! /usr/bin/env python
# -*- coding: utf-8 -
+from flask import Blueprint, g, render_template, redirect, flash, url_for
+from flask.ext.babel import gettext
+from flask.ext.login import login_required
-from flask import Blueprint, g, render_template, redirect
-
-from web import controllers, utils
+from web.lib.utils import clear_string, redirect_url
+from web.controllers import ArticleController
from web.lib.view_utils import etag_match
-from web.decorators import pyagg_default_decorator
articles_bp = Blueprint('articles', __name__, url_prefix='/articles')
article_bp = Blueprint('article', __name__, url_prefix='/article')
@article_bp.route('/redirect/<int:article_id>', methods=['GET'])
-@pyagg_default_decorator
+@login_required
def redirect_to_article(article_id):
- article = controllers.ArticleController(g.user.id).get(id=article_id)
+ article = ArticleController(g.user.id).get(id=article_id)
return redirect(article.link)
@article_bp.route('/<int:article_id>', methods=['GET'])
-@pyagg_default_decorator
+@login_required
@etag_match
def article(article_id=None):
"""
Presents the content of an article.
"""
- article = controllers.ArticleController(g.user.id).get(id=article_id)
+ article = ArticleController(g.user.id).get(id=article_id)
previous_article = article.previous_article()
if previous_article is None:
previous_article = article.source.articles[0]
@@ -34,7 +35,69 @@ def article(article_id=None):
next_article = article.source.articles[-1]
return render_template('article.html',
- head_titles=[utils.clear_string(article.title)],
+ head_titles=[clear_string(article.title)],
article=article,
previous_article=previous_article,
next_article=next_article)
+
+
+@article_bp.route('/like/<int:article_id>', methods=['GET'])
+@login_required
+def like(article_id=None):
+ """
+ Mark or unmark an article as favorites.
+ """
+ art_contr = ArticleController(g.user.id)
+ article = art_contr.get(id=article_id)
+ art_contr = art_contr.update({'id': article_id},
+ {'like': not article.like})
+ return redirect(redirect_url())
+
+
+@article_bp.route('/delete/<int:article_id>', methods=['GET'])
+@login_required
+def delete(article_id=None):
+ """
+ Delete an article from the database.
+ """
+ article = ArticleController(g.user.id).delete(article_id)
+ flash(gettext('Article %(article_title)s deleted',
+ article_title=article.title), 'success')
+ return redirect(url_for('home'))
+
+
+@articles_bp.route('/history', methods=['GET'])
+@articles_bp.route('/history/<int:year>', methods=['GET'])
+@articles_bp.route('/history/<int:year>/<int:month>', methods=['GET'])
+@login_required
+def history(year=None, month=None):
+ counter, articles = ArticleController(g.user.id).get_history(year, month)
+ return render_template('history.html', articles_counter=counter,
+ articles=articles, year=year, month=month)
+
+
+@article_bp.route('/mark_as/<string:new_value>', methods=['GET'])
+@article_bp.route('/mark_as/<string:new_value>/article/<int:article_id>',
+ methods=['GET'])
+@login_required
+def mark_as(new_value='read', feed_id=None, article_id=None):
+ """
+ Mark all unreaded articles as read.
+ """
+ readed = new_value == 'read'
+ art_contr = ArticleController(g.user.id)
+ filters = {'readed': not readed}
+ if feed_id is not None:
+ filters['feed_id'] = feed_id
+ message = 'Feed marked as %s.'
+ elif article_id is not None:
+ filters['id'] = article_id
+ message = 'Article marked as %s.'
+ else:
+ message = 'All article marked as %s.'
+ art_contr.update(filters, {"readed": readed})
+ flash(gettext(message % new_value), 'info')
+
+ if readed:
+ return redirect(redirect_url())
+ return redirect('home')
diff --git a/src/web/views/feed.py b/src/web/views/feed.py
index 68d8765a..6569d1b7 100644
--- a/src/web/views/feed.py
+++ b/src/web/views/feed.py
@@ -217,3 +217,29 @@ def process_form(feed_id=None):
flash(gettext("Downloading articles for the new feed..."), 'info')
return redirect(url_for('feed.form', feed_id=new_feed.id))
+
+
+@feeds_bp.route('/inactives', methods=['GET'])
+@login_required
+def inactives():
+ """
+ List of inactive feeds.
+ """
+ nb_days = int(request.args.get('nb_days', 365))
+ inactives = FeedController(g.user.id).get_inactives(nb_days)
+ return render_template('inactives.html',
+ inactives=inactives, nb_days=nb_days)
+
+
+@feed_bp.route('/duplicates/<int:feed_id>', methods=['GET'])
+@login_required
+def duplicates(feed_id):
+ """
+ Return duplicates article for a feed.
+ """
+ feed, duplicates = FeedController(g.user.id).get_duplicates(feed_id)
+ if len(duplicates) == 0:
+ flash(gettext('No duplicates in the feed "{}".').format(feed.title),
+ 'info')
+ return redirect('home')
+ return render_template('duplicates.html', duplicates=duplicates, feed=feed)
diff --git a/src/web/views/views.py b/src/web/views/views.py
index ed4ae8a7..1e7b7539 100644
--- a/src/web/views/views.py
+++ b/src/web/views/views.py
@@ -38,8 +38,7 @@ from bootstrap import application as app, db
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, \
- login_url
+ login_required, current_user, AnonymousUserMixin
from flask.ext.principal import Principal, Identity, AnonymousIdentity, \
identity_changed, identity_loaded, Permission,\
RoleNeed, UserNeed
@@ -49,6 +48,7 @@ from sqlalchemy.exc import IntegrityError
from werkzeug import generate_password_hash
import conf
+from web.lib.utils import redirect_url
from web import utils, notifications, export
from web.lib.view_utils import etag_match
from web.models import User, Feed, Article, Role
@@ -90,6 +90,7 @@ def on_identity_loaded(sender, identity):
for role in current_user.roles:
identity.provides.add(RoleNeed(role.name))
+
@app.before_request
def before_request():
g.user = current_user
@@ -98,6 +99,7 @@ def before_request():
db.session.add(g.user)
db.session.commit()
+
@login_manager.user_loader
def load_user(id):
# Return an instance of the User model
@@ -111,15 +113,18 @@ def authentication_required(e):
flash(gettext('Authentication required.'), 'info')
return redirect(url_for('login'))
+
@app.errorhandler(403)
def authentication_failed(e):
flash(gettext('Forbidden.'), 'danger')
return redirect(url_for('login'))
+
@app.errorhandler(404)
def page_not_found(e):
return render_template('errors/404.html'), 404
+
@app.errorhandler(500)
def internal_server_error(e):
return render_template('errors/500.html'), 500
@@ -138,6 +143,7 @@ def get_locale():
"""
return request.accept_languages.best_match(conf.LANGUAGES.keys())
+
@g.babel.timezoneselector
def get_timezone():
try:
@@ -167,6 +173,7 @@ def login():
return form.redirect('home')
return render_template('login.html', form=form)
+
@app.route('/logout')
@login_required
def logout():
@@ -367,97 +374,6 @@ def about():
return render_template('about.html')
-@app.route('/mark_as/<string:new_value>', methods=['GET'])
-@app.route('/mark_as/<string:new_value>/article/<int:article_id>', methods=['GET'])
-@login_required
-@feed_access_required
-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:
- 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:
- message = 'All article marked as %s.'
- articles.filter(Article.readed == (not readed)).update({"readed": readed})
- flash(gettext(message % new_value), 'info')
- db.session.commit()
- if readed:
- return redirect(redirect_url())
- return redirect(url_for('home'))
-
-@app.route('/like/<int:article_id>', methods=['GET'])
-@login_required
-def like(article_id=None):
- """
- Mark or unmark an article as favorites.
- """
- Article.query.filter(Article.user_id == g.user.id, Article.id == article_id). \
- update({
- "like": not Article.query.filter(Article.id == article_id).first().like
- })
- db.session.commit()
- return redirect(redirect_url())
-
-@app.route('/delete/<int:article_id>', methods=['GET'])
-@login_required
-def delete(article_id=None):
- """
- Delete an article from the database.
- """
- article = Article.query.filter(Article.id == article_id).first()
- if article is not None and article.source.subscriber.id == g.user.id:
- db.session.delete(article)
- db.session.commit()
- flash(gettext('Article') + ' ' + article.title + ' ' + gettext('deleted.'), 'success')
- return redirect(redirect_url())
- else:
- flash(gettext('This article do not exist.'), 'danger')
- return redirect(url_for('home'))
-
-
-@app.route('/inactives', methods=['GET'])
-@login_required
-def inactives():
- """
- List of inactive feeds.
- """
- nb_days = int(request.args.get('nb_days', 365))
- user = UserController(g.user.id).get(email=g.user.email)
- today = datetime.datetime.now()
- inactives = []
- for feed in user.feeds:
- try:
- last_post = feed.articles[0].date
- except IndexError:
- continue
- elapsed = today - last_post
- if elapsed > datetime.timedelta(days=nb_days):
- inactives.append((feed, elapsed))
- inactives.sort(key=lambda tup: tup[1], reverse=True)
- return render_template('inactives.html', inactives=inactives, nb_days=nb_days)
-
-@app.route('/duplicates/<int:feed_id>', methods=['GET'])
-@login_required
-def duplicates(feed_id=None):
- """
- Return duplicates article for a feed.
- """
- feed = Feed.query.filter(Feed.user_id == g.user.id, Feed.id == feed_id).first()
- duplicates = []
- duplicates = utils.compare_documents(feed)
- if len(duplicates) == 0:
- flash(gettext('No duplicates in the feed "{}".').format(feed.title),
- 'info')
- return redirect(redirect_url())
- return render_template('duplicates.html', duplicates=duplicates, feed=feed)
-
@app.route('/export', methods=['GET'])
@login_required
def export_articles():
@@ -485,12 +401,14 @@ def export_articles():
return redirect(redirect_url())
response = make_response(json_result)
response.mimetype = 'application/json'
- response.headers["Content-Disposition"] = 'attachment; filename=account.json'
+ response.headers["Content-Disposition"] \
+ = 'attachment; filename=account.json'
else:
flash(gettext('Export format not supported.'), 'warning')
return redirect(redirect_url())
return response
+
@app.route('/export_opml', methods=['GET'])
@login_required
def export_opml():
@@ -551,17 +469,6 @@ def management():
nb_feeds=nb_feeds, nb_articles=nb_articles,
nb_unread_articles=nb_unread_articles)
-@app.route('/history', methods=['GET'])
-@app.route('/history/<int:year>', methods=['GET'])
-@app.route('/history/<int:year>/<int:month>', methods=['GET'])
-@login_required
-def history(year=None, month=None):
- 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('/profile', methods=['GET', 'POST'])
@login_required
bgstack15