support excluding feeds from the front page

and some style/UI tweaks
This commit is contained in:
Kyle Mahan 2015-12-07 15:46:47 +00:00
parent 190bb1eb55
commit bca07e2178
11 changed files with 77 additions and 28 deletions

View file

@ -99,7 +99,9 @@ class Subscription(db.Model):
# user-editable name of this subscribed feed
name = db.Column(db.String(256))
tags = db.Column(db.String(256))
# exclude from the front page
exclude = db.Column(db.Boolean, default=False)
user = db.relationship(User, backref='subscriptions')
feed = db.relationship(Feed, backref='subscriptions')

View file

@ -64,15 +64,16 @@ $(function(){
function attachListeners() {
$("#older-link").off('click').click(clickOlderLink);
$(".micropub-form button[type='submit']").off('click').click(submitMicropubForm);
$(".reply-area").hide();
$(".reply-area.closed").hide();
$("article").off('click').click(function(evt) {
var $target = $(evt.target);
if ($target.closest("form, a, video, audio").length == 0) {
$(".reply-area", this).toggleClass("closed");
$(".reply-area", this).slideToggle(200);
}
});
}

View file

@ -360,7 +360,8 @@ th {
/* Subtlety of Hue */
body {
font: 12pt Helvetica, Arial, sans-serif;
background: #ecebf0;
/*background: $athens-gray;*/
background: #f4f4f4;
padding-top: 1em; }
a {
@ -410,12 +411,13 @@ ul#navigation {
article {
margin-bottom: 2em;
box-shadow: 0 0 2px #687d77;
background-color: white;
/*box-shadow: $box-shadow;
background-color: white;*/
padding: 0.5em; }
article.reply-context {
margin-bottom: 0;
background-color: #f3f3f3; }
background-color: #e0e0e0;
color: #555; }
article.reply-context .content img {
max-height: 240px;
max-width: 240px; }

View file

@ -17,7 +17,8 @@ $box-shadow: 0 0 2px $sirocco;
body {
font: 12pt $body-font;
background: $athens-gray;
/*background: $athens-gray;*/
background: #f4f4f4;
padding-top: 1em;
}
@ -86,13 +87,14 @@ ul#navigation {
article {
margin-bottom: 2em;
box-shadow: $box-shadow;
background-color: white;
/*box-shadow: $box-shadow;
background-color: white;*/
padding: 0.5em;
&.reply-context {
margin-bottom: 0;
background-color: #f3f3f3;
background-color: #e0e0e0;
color: #555;
.content img {
max-height: 240px;
max-width: 240px;
@ -246,10 +248,10 @@ button {
.reply-area {
text-align: center;
margin-top: 0.5em;
.content {
height: 4em;
}
}
.reply-link {
display: inline-block;

View file

@ -18,8 +18,20 @@ $(function() {
}).fail(function failure() {
$(".save-status", form).html("Save Failed!");
});
});
$("form.poll-now").submit(function(evt) {
var form = $(this);
evt.preventDefault();
$(".poll-status", form).html("");
$.post(form.attr('action'), form.serialize(), function success(){
$(".poll-status", form).html("Poll Requested.");
}).fail(function failure() {
$(".poll-status", form).html("Polling Failed!");
});
});
});

View file

@ -311,8 +311,13 @@ def notify_feed_updated(app, feed_id, entry_ids):
'subscription': s.id,
'entries': rendered,
})
for topic in ('user:{}'.format(s.user.id),
'subsc:{}'.format(s.id)):
topics = []
if not s.exclude:
topics.append('user:{}'.format(s.user.id))
topics.append('subsc:{}'.format(s.id))
for topic in topics:
redis.publish('woodwind_notify:{}'.format(topic), message)

View file

@ -73,7 +73,7 @@
| {% for synd in entry.get_property('syndication') %} <a href="{{ synd }}">{{ synd | domain_for_url}}</a>{% endfor %}
{% endif %}
<div class="reply-area">
<div class="reply-area closed">
{% include '_reply.jinja2' with context %}
</div>
</footer>

View file

@ -8,7 +8,7 @@
<link rel="shortcut icon" href="{{ url_for('static', filename='logo.png') }}"/>
<link rel="apple-touch-icon" href="{{ url_for('static', filename='logo.png') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css', version='2015-10-07') }}"/>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css', version='2015-11-25') }}"/>
<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>
<script src="{{ url_for('static', filename='moment.min.js') }}"></script>

View file

@ -4,7 +4,7 @@
{% if ws_topic %}
<script>var WS_TOPIC = "{{ ws_topic }}";</script>
{% endif %}
<script src="{{url_for('static', filename='feed.js', version='2015-10-08')}}"></script>
<script src="{{url_for('static', filename='feed.js', version='2015-11-06')}}"></script>
{% if current_user and current_user.settings
and current_user.settings.get('reply-method') == 'indie-config' %}

View file

@ -38,6 +38,12 @@
<input type="text" name="tags" value="{{ s.tags or ''}}"/>
<label>URL</label>
<input type="text" name="feed" value="{{ s.feed.feed }}" readonly />
<label style="display: block; font-weight: normal;">
<input type="checkbox" name="exclude" value="true" {% if s.exclude %}checked{% endif %} />
Exclude from primary feed
</label>
<button type="submit">Save Edits</button> <span class="save-status"></span>
</form>
@ -63,14 +69,14 @@
</div>
<form action="{{ url_for('.update_feed') }}" method="POST" style="display:inline">
<form class="poll-now" action="{{ url_for('.update_feed') }}" method="POST" style="display:inline">
<input type="hidden" name="id" value="{{ s.feed.id }}"/>
<button type="submit">Poll Now</button>
<button type="submit">Poll Now</button> <span class="poll-status"></span>
</form>
<form action="{{ url_for('.unsubscribe') }}" method="POST" style="display:inline">
<form class="unsubscribe" action="{{ url_for('.unsubscribe') }}" method="POST" style="display:inline">
<input type="hidden" name="id" value="{{ s.id }}"/>
<button type="submit">Unsubscribe</button>
<button type="submit">Unsubscribe</button> <span class="unsubscribe-status"></span>
</form>

View file

@ -2,7 +2,8 @@ from . import tasks, util
from .extensions import db, login_mgr, micropub
from .models import Feed, Entry, User, Subscription
import flask.ext.login as flask_login
import binascii
import base64
import bs4
import datetime
import feedparser
@ -74,6 +75,7 @@ def index():
entry_query = entry_query.filter(
sqlalchemy.sql.expression.cast(Entry.properties['jam'], sqlalchemy.TEXT) == 'true')
else:
entry_query = entry_query.filter(Subscription.exclude == False)
ws_topic = 'user:{}'.format(flask_login.current_user.id)
entry_query = entry_query.order_by(Entry.retrieved.desc(),
@ -226,6 +228,7 @@ def edit_subscription():
subsc.tags = ' '.join(t.strip() for t in tag_list if t.strip())
else:
subsc.tags = None
subsc.exclude = flask.request.form.get('exclude') == 'true'
db.session.commit()
flask.flash('Edited {}'.format(subsc.name))
@ -609,13 +612,29 @@ def add_preview(content):
@views.app_template_filter()
def proxy_image(url):
proxy_url = flask.current_app.config.get('IMAGEPROXY_URL')
proxy_key = flask.current_app.config.get('IMAGEPROXY_KEY')
if proxy_url and proxy_key:
sig = base64.urlsafe_b64encode(
hmac.new(proxy_key.encode(), url.encode(), hashlib.sha256).digest()
).decode()
return '/'.join((proxy_url.rstrip('/'), 's' + sig, url))
pilbox_url = flask.current_app.config.get('PILBOX_URL')
pilbox_key = flask.current_app.config.get('PILBOX_KEY')
if pilbox_url and pilbox_key:
query = urllib.parse.urlencode({'url': url, 'op': 'noop'})
sig = hmac.new(pilbox_key.encode(), query.encode(), hashlib.sha1).hexdigest()
query += '&sig=' + sig
return pilbox_url + '?' + query
camo_url = flask.current_app.config.get('CAMO_URL')
camo_key = flask.current_app.config.get('CAMO_KEY')
if not camo_url or not camo_key:
return url
digest = hmac.new(camo_key.encode(), url.encode(), hashlib.sha1).hexdigest()
return (urllib.parse.urljoin(camo_url, digest)
+ '?url=' + urllib.parse.quote_plus(url))
if camo_url and camo_key:
digest = hmac.new(camo_key.encode(), url.encode(), hashlib.sha1).hexdigest()
return (urllib.parse.urljoin(camo_url, digest)
+ '?url=' + urllib.parse.quote_plus(url))
return url
@views.app_template_filter()