support tagging subscriptions
This commit is contained in:
parent
9cfa2e4739
commit
c9b2366637
11 changed files with 80 additions and 37 deletions
|
@ -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')
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 396 B |
25
woodwind/static/subscriptions.js
Normal file
25
woodwind/static/subscriptions.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
$(function() {
|
||||
|
||||
$(".feed-details").css({display: "none"});
|
||||
|
||||
$(".show-details").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var target = $(this).data("target");
|
||||
$("#" + target).css({display: "inherit"});
|
||||
$(this).css({display: "none"});
|
||||
});
|
||||
|
||||
$("form.edit-subscription").submit(function(evt) {
|
||||
var form = $(this);
|
||||
evt.preventDefault();
|
||||
$(".save-status", form).html("Saving…");
|
||||
$.post(form.attr('action'), form.serialize(), function success(){
|
||||
$(".save-status", form).html("Saved.");
|
||||
}).fail(function failure() {
|
||||
$(".save-status", form).html("Save Failed!");
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -51,7 +51,7 @@
|
|||
<footer>
|
||||
<a href="{{ entry.permalink }}">{{ entry.published | relative_time }}</a>
|
||||
<a href="{{ url_for('.index', entry=entry.permalink) }}" target="_blank">
|
||||
<img src="{{ url_for('static', filename='open_in_new_window2.png') }}" style="vertical-align:middle;" />
|
||||
<i class="fa fa-external-link"></i>
|
||||
</a>
|
||||
|
||||
{% if entry._syndicated_copies %}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css', version='2015-03-20a') }}"/>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"/>
|
||||
<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
<input type="url" id="origin" name="origin" placeholder="Subscribe to URL" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<i class="fa fa-tags"></i>
|
||||
{% for tag in all_tags %}
|
||||
<a href="{{ url_for('.index', tag=tag) }}">{{ tag }}</a>{% 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 %}
|
||||
<div class="pager">
|
||||
<a id="older-link" href="{{ url_for_other_page(page=page+1) }}">Older</a>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{% extends "base.jinja2" %}
|
||||
|
||||
{% block head %}
|
||||
<script src="{{url_for('static', filename='subscriptions.js', version='2015-04-19')}}"></script>
|
||||
{% endblock head %}
|
||||
|
||||
{% block header %}
|
||||
{% if current_user.is_authenticated() %}
|
||||
<form action="{{ url_for('.subscribe') }}" method="POST">
|
||||
|
@ -24,12 +28,12 @@
|
|||
<form class="edit-subscription" action="{{ url_for('.edit_subscription') }}" method="POST">
|
||||
<input type="hidden" name="id" value="{{ s.id }}"/>
|
||||
<label>Name</label>
|
||||
<input type="text" name="name" value="{{ s.name }}"/>
|
||||
<input type="text" name="name" value="{{ s.name }}"/>
|
||||
<label>Tags</label>
|
||||
<input type="text" name="tags" value="{{ (s.tags or []) | join(',') }}"/>
|
||||
<input type="text" name="tags" value="{{ s.tags or ''}}"/>
|
||||
<label>URL</label>
|
||||
<input type="text" name="feed" value="{{ s.feed.feed }}" disabled />
|
||||
<button type="submit">Save Edits</button>
|
||||
<button type="submit">Save Edits</button> <span class="save-status"></span>
|
||||
</form>
|
||||
|
||||
|
||||
|
@ -69,19 +73,5 @@
|
|||
|
||||
{% endblock body %}
|
||||
{% block foot %}
|
||||
<script>
|
||||
$(function() {
|
||||
|
||||
$(".feed-details").css({display: "none"});
|
||||
|
||||
$(".show-details").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var target = $(this).data("target");
|
||||
$("#" + target).css({display: "inherit"});
|
||||
$(this).css({display: "none"});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock foot %}
|
||||
|
|
|
@ -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'))
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue