From c9b23666377da6394886ef5547d1b46a5c1813b3 Mon Sep 17 00:00:00 2001 From: Kyle Mahan Date: Sun, 19 Apr 2015 13:58:31 -0700 Subject: [PATCH] support tagging subscriptions --- migrations/versions/564f5a5061f_.py | 2 +- woodwind/extensions.py | 6 +-- woodwind/models.py | 2 +- woodwind/static/open_in_new_window.png | Bin 1568 -> 0 bytes woodwind/static/open_in_new_window2.png | Bin 396 -> 0 bytes woodwind/static/subscriptions.js | 25 +++++++++++++ woodwind/templates/_entry.jinja2 | 2 +- woodwind/templates/base.jinja2 | 1 + woodwind/templates/feed.jinja2 | 8 +++- woodwind/templates/subscriptions.jinja2 | 24 ++++-------- woodwind/views.py | 47 +++++++++++++++++------- 11 files changed, 80 insertions(+), 37 deletions(-) delete mode 100644 woodwind/static/open_in_new_window.png delete mode 100644 woodwind/static/open_in_new_window2.png create mode 100644 woodwind/static/subscriptions.js diff --git a/migrations/versions/564f5a5061f_.py b/migrations/versions/564f5a5061f_.py index ab01906..37bdedc 100644 --- a/migrations/versions/564f5a5061f_.py +++ b/migrations/versions/564f5a5061f_.py @@ -23,7 +23,7 @@ def upgrade(): sa.Column('user_id', sa.Integer(), sa.ForeignKey('user.id'), nullable=False), sa.Column('feed_id', sa.Integer(), sa.ForeignKey('feed.id'), nullable=False), sa.Column('name', sa.String(length=256), nullable=True), - sa.Column('tags', JsonType(), nullable=True), + sa.Column('tags', sa.String(length=256), nullable=True), sa.PrimaryKeyConstraint('id') ) diff --git a/woodwind/extensions.py b/woodwind/extensions.py index 2cd75fe..44e8b1f 100644 --- a/woodwind/extensions.py +++ b/woodwind/extensions.py @@ -1,7 +1,7 @@ from flask.ext.login import LoginManager from flask.ext.micropub import MicropubClient from flask.ext.sqlalchemy import SQLAlchemy -#from flask_debugtoolbar import DebugToolbarExtension +from flask_debugtoolbar import DebugToolbarExtension from flask.ext.migrate import Migrate @@ -9,7 +9,7 @@ db = SQLAlchemy() micropub = MicropubClient(client_id='http://reader.kylewm.com') login_mgr = LoginManager() login_mgr.login_view = 'views.index' -#toolbar = DebugToolbarExtension() +toolbar = DebugToolbarExtension() migrate = Migrate() @@ -17,5 +17,5 @@ def init_app(app): db.init_app(app) micropub.init_app(app) login_mgr.init_app(app) - #toolbar.init_app(app) + toolbar.init_app(app) migrate.init_app(app, db) diff --git a/woodwind/models.py b/woodwind/models.py index dfea7fc..b46bb3a 100644 --- a/woodwind/models.py +++ b/woodwind/models.py @@ -112,7 +112,7 @@ class Subscription(db.Model): # user-editable name of this subscribed feed name = db.Column(db.String(256)) - tags = db.Column(JsonType) + tags = db.Column(db.String(256)) user = db.relationship(User, backref='subscriptions') feed = db.relationship(Feed, backref='subscriptions') diff --git a/woodwind/static/open_in_new_window.png b/woodwind/static/open_in_new_window.png deleted file mode 100644 index 3e595aa83ee575ad1a9d46e9475d28357f10e692..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1568 zcmbtUYfuwc7`;niK?@03l>kCw9nn6aKnE#-gbGy(6A%yqQ6dtlRY^gRhc;}WqoEN~ z!72>c_^8&}7G~-LMe9agl2Ry?>I`6oAdv8?n2koWx+cA#ojPOdk9L3Tx%d0Nd(PSK z-n$j?!euTqJ!b*{T%wmpCIEoIAp)FG2WRcwJU;ZmXCFfWwvO$cUt(8-MhLC3}9t*4&z(&@;wtXXZP`A6KMCh-Re9dLwSi zn#*eD*taF^oqB!b{(8X6JFAHW^TN>@ir-z(ar#o@RXPWatQJGn7d+~+G$9f*zQo~7 z-g?lpUqO$CxQy{C@I0$)X*vo>FW`zJPeDMl0ii_x56sQuN|U>`&8(7_e$H7WbeIGL z3l-3!zrnUK#G%r(hW?Ok2<=clqS=m1utU&>(>xr()K3QjS~e66DsqzUgqK|8b7VqruIlHdoy~ee1PS_kp91iL`7G&-b7UhLhX3 zlpgxssxWOQeXw9F!3mNwj4a8poS#OchpxNrvM@9%0wj^XqVCn)e&b8Vof*1g#sCgw zZs**t)y05DTMLILWyBw?9&ojtg&l#doNCNJKwKsmH{G#oe?(0jQ=QJaxtKpm*Q=WQ zkou4x&&)N~@@qqZEr>lq+^NNHIfKDqz?Cwd0eJ=uPlG}S!*CA>KPdyVv`FCLu(*Ih zNfE8>^0{|*!iTi2ppyp{uYTOAy1)?7E_?8ig<#Mfhld7IzL4bKima9Oeo(AjqkBRC znP4dthVsw{bVDkjIqutGqyiUeym%e=!UM~48A=7w(Bxb1R|sZ|XV2N;L+J4l*-j7eZ|2;!P-}>EeC@i3tNGDJUr;Jmp^c=K>!1=ff@i5_yY_9&OikI za|jE$@s7L1!lYseib%8y1 ztxd{Pts`i&{-8|hc51S2dy_uUdZwE)bFkE-BBvBhW#S8drcKVqjn@ z2!e`u>zVY*xbC%reo)YKQPp4ltNEgOrDWZ-QVi;*9pK+|KE?3d|3vX`{Ka@is0s$= z>!uyyXUS#Nd1-OVW`*s19%BLLn0v>dZrVRsFFdq`6AW;RVP?>qjIfSl98DDta^V^J zc)%*IyEZ2}OEDaFAz~Sqo#M@W_o{xu_5!Z5i+lXSDBnXWHb^ntVJ`z*!BS?{!$pc= zqi))w11W|B{J>3TLw&4GwpV@hRZ|R)9VYOUVi?bYxKlUnexcX$EN+tqC)mwV(k)Kk qY$4CGlVa#);{S^(#W2LP@6-#s%vT6(BJ>#m0000 {{ entry.published | relative_time }} - + {% if entry._syndicated_copies %} diff --git a/woodwind/templates/base.jinja2 b/woodwind/templates/base.jinja2 index 1f368da..4573a71 100644 --- a/woodwind/templates/base.jinja2 +++ b/woodwind/templates/base.jinja2 @@ -11,6 +11,7 @@ + {% block head %}{% endblock %} diff --git a/woodwind/templates/feed.jinja2 b/woodwind/templates/feed.jinja2 index 4966d40..e3f4565 100644 --- a/woodwind/templates/feed.jinja2 +++ b/woodwind/templates/feed.jinja2 @@ -20,6 +20,12 @@ {% endif %} + + + {% for tag in all_tags %} + {{ tag }}{% if not loop.last %}, {% endif %} + {% endfor %} + {% endblock header %} {% block body %} @@ -28,7 +34,7 @@ {% include '_entry.jinja2' with context %} {% endfor %} - {% if entries and has_older %} + {% if not solo %} diff --git a/woodwind/templates/subscriptions.jinja2 b/woodwind/templates/subscriptions.jinja2 index 2b04a0d..e556ae5 100644 --- a/woodwind/templates/subscriptions.jinja2 +++ b/woodwind/templates/subscriptions.jinja2 @@ -1,5 +1,9 @@ {% extends "base.jinja2" %} +{% block head %} + +{% endblock head %} + {% block header %} {% if current_user.is_authenticated() %}
@@ -24,12 +28,12 @@ - + - + - +
@@ -69,19 +73,5 @@ {% endblock body %} {% block foot %} - {% endblock foot %} diff --git a/woodwind/views.py b/woodwind/views.py index 13cc370..dec2a74 100644 --- a/woodwind/views.py +++ b/woodwind/views.py @@ -23,15 +23,22 @@ def index(): page = int(flask.request.args.get('page', 1)) entries = [] ws_topic = None - has_older = True + solo = False if flask_login.current_user.is_authenticated(): + all_tags = set() + for subsc in flask_login.current_user.subscriptions: + if subsc.tags: + all_tags.update(subsc.tags.split()) + per_page = flask.current_app.config.get('PER_PAGE', 30) offset = (page - 1) * per_page entry_query = Entry.query\ - .options(sqlalchemy.orm.subqueryload(Entry.feed), - sqlalchemy.orm.subqueryload(Entry.reply_context))\ + .options( + sqlalchemy.orm.subqueryload(Entry.feed), + sqlalchemy.orm.subqueryload(Entry.reply_context) + )\ .join(Entry.feed)\ .join(Feed.subscriptions)\ .join(Subscription.user)\ @@ -45,9 +52,13 @@ def index(): if not entry: flask.abort(404) entries = [entry] - has_older = False + solo = True else: - if 'subscription' in flask.request.args: + if 'tag' in flask.request.args: + tag = flask.request.args.get('tag') + entry_query = entry_query.filter( + Subscription.tags.like('%{}%'.format(tag))) + elif 'subscription' in flask.request.args: subsc_id = flask.request.args.get('subscription') subsc = Subscription.query.get(subsc_id) if not subsc: @@ -63,7 +74,8 @@ def index(): entries = dedupe_copies(entries) return flask.render_template('feed.jinja2', entries=entries, page=page, - ws_topic=ws_topic, has_older=has_older) + ws_topic=ws_topic, solo=solo, + all_tags=all_tags) @views.route('/install') @@ -75,10 +87,16 @@ def install(): @views.route('/subscriptions') @flask_login.login_required def subscriptions(): - subscs = flask_login.current_user.subscriptions - sorted_subscs = sorted(subscs, key=lambda s: s.name and s.name.lower()) + + subscs = Subscription\ + .query\ + .filter_by(user_id=flask_login.current_user.id)\ + .options(sqlalchemy.orm.subqueryload(Subscription.feed))\ + .order_by(db.func.lower(Subscription.name))\ + .all() + return flask.render_template('subscriptions.jinja2', - subscriptions=sorted_subscs) + subscriptions=subscs) @views.route('/settings', methods=['GET', 'POST']) @@ -140,16 +158,19 @@ def unsubscribe(): def edit_subscription(): subsc_id = flask.request.form.get('id') subsc_name = flask.request.form.get('name') - #feed_url = flask.request.form.get('feed') + subsc_tags = flask.request.form.get('tags') subsc = Subscription.query.get(subsc_id) if subsc_name: subsc.name = subsc_name - #if feed_url: - # feed.feed = feed_url + if subsc_tags: + tag_list = re.split(r'(?:\s|,)+', subsc_tags) + subsc.tags = ' '.join(t.strip() for t in tag_list if t.strip()) + else: + subsc_tags = None db.session.commit() - flask.flash('Edited {} ({})'.format(subsc.name)) + flask.flash('Edited {}'.format(subsc.name)) return flask.redirect(flask.url_for('.subscriptions'))