mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 11:26:56 -08:00
active sort with user default sort choice
This commit is contained in:
parent
c3d83b1428
commit
eee7c59b57
9 changed files with 67 additions and 12 deletions
|
@ -101,7 +101,7 @@ def show_community(community: Community):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
page = request.args.get('page', 1, type=int)
|
page = request.args.get('page', 1, type=int)
|
||||||
sort = request.args.get('sort', '')
|
sort = request.args.get('sort', '' if current_user.is_anonymous else current_user.default_sort)
|
||||||
|
|
||||||
# If nothing has changed since their last visit, return HTTP 304
|
# If nothing has changed since their last visit, return HTTP 304
|
||||||
current_etag = f"{community.id}{sort}_{hash(community.last_active)}"
|
current_etag = f"{community.id}{sort}_{hash(community.last_active)}"
|
||||||
|
@ -133,6 +133,8 @@ def show_community(community: Community):
|
||||||
posts = posts.filter(Post.posted_at > utcnow() - timedelta(days=7)).order_by(desc(Post.score))
|
posts = posts.filter(Post.posted_at > utcnow() - timedelta(days=7)).order_by(desc(Post.score))
|
||||||
elif sort == 'new':
|
elif sort == 'new':
|
||||||
posts = posts.order_by(desc(Post.posted_at))
|
posts = posts.order_by(desc(Post.posted_at))
|
||||||
|
elif sort == 'active':
|
||||||
|
posts = posts.order_by(desc(Post.last_active))
|
||||||
posts = posts.paginate(page=page, per_page=100, error_out=False)
|
posts = posts.paginate(page=page, per_page=100, error_out=False)
|
||||||
|
|
||||||
description = shorten_string(community.description, 150) if community.description else None
|
description = shorten_string(community.description, 150) if community.description else None
|
||||||
|
@ -151,7 +153,7 @@ def show_community(community: Community):
|
||||||
next_url=next_url, prev_url=prev_url, low_bandwidth=request.cookies.get('low_bandwidth', '0') == '1',
|
next_url=next_url, prev_url=prev_url, low_bandwidth=request.cookies.get('low_bandwidth', '0') == '1',
|
||||||
rss_feed=f"https://{current_app.config['SERVER_NAME']}/community/{community.link()}/feed", rss_feed_name=f"{community.title} posts on PieFed",
|
rss_feed=f"https://{current_app.config['SERVER_NAME']}/community/{community.link()}/feed", rss_feed_name=f"{community.title} posts on PieFed",
|
||||||
content_filters=content_filters, moderating_communities=moderating_communities(current_user.get_id()),
|
content_filters=content_filters, moderating_communities=moderating_communities(current_user.get_id()),
|
||||||
joined_communities=joined_communities(current_user.get_id()))
|
joined_communities=joined_communities(current_user.get_id()), sort=sort)
|
||||||
|
|
||||||
|
|
||||||
# RSS feed of the community
|
# RSS feed of the community
|
||||||
|
|
|
@ -25,7 +25,7 @@ import pytesseract
|
||||||
@bp.route('/', methods=['HEAD', 'GET', 'POST'])
|
@bp.route('/', methods=['HEAD', 'GET', 'POST'])
|
||||||
@bp.route('/home', methods=['GET', 'POST'])
|
@bp.route('/home', methods=['GET', 'POST'])
|
||||||
@bp.route('/home/<sort>', methods=['GET', 'POST'])
|
@bp.route('/home/<sort>', methods=['GET', 'POST'])
|
||||||
def index(sort='hot'):
|
def index(sort=None):
|
||||||
if 'application/ld+json' in request.headers.get('Accept', '') or 'application/activity+json' in request.headers.get(
|
if 'application/ld+json' in request.headers.get('Accept', '') or 'application/activity+json' in request.headers.get(
|
||||||
'Accept', ''):
|
'Accept', ''):
|
||||||
return activitypub_application()
|
return activitypub_application()
|
||||||
|
@ -35,21 +35,24 @@ def index(sort='hot'):
|
||||||
|
|
||||||
@bp.route('/popular', methods=['GET'])
|
@bp.route('/popular', methods=['GET'])
|
||||||
@bp.route('/popular/<sort>', methods=['GET'])
|
@bp.route('/popular/<sort>', methods=['GET'])
|
||||||
def popular(sort='hot'):
|
def popular(sort=None):
|
||||||
return home_page('popular', sort)
|
return home_page('popular', sort)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/all', methods=['GET'])
|
@bp.route('/all', methods=['GET'])
|
||||||
@bp.route('/all/<sort>', methods=['GET'])
|
@bp.route('/all/<sort>', methods=['GET'])
|
||||||
def all_posts(sort='hot'):
|
def all_posts(sort=None):
|
||||||
return home_page('all', sort)
|
return home_page('all', sort)
|
||||||
|
|
||||||
|
|
||||||
def home_page(type, sort='hot'):
|
def home_page(type, sort):
|
||||||
verification_warning()
|
verification_warning()
|
||||||
|
|
||||||
|
if sort is None:
|
||||||
|
sort = current_user.default_sort if current_user.is_authenticated else 'hot'
|
||||||
|
|
||||||
# If nothing has changed since their last visit, return HTTP 304
|
# If nothing has changed since their last visit, return HTTP 304
|
||||||
current_etag = f"{type}_{hash(str(g.site.last_active))}"
|
current_etag = f"{type}_{sort}_{hash(str(g.site.last_active))}"
|
||||||
if current_user.is_anonymous and request_etag_matches(current_etag):
|
if current_user.is_anonymous and request_etag_matches(current_etag):
|
||||||
return return_304(current_etag)
|
return return_304(current_etag)
|
||||||
|
|
||||||
|
@ -92,6 +95,8 @@ def home_page(type, sort='hot'):
|
||||||
posts = posts.filter(Post.posted_at > utcnow() - timedelta(days=1)).order_by(desc(Post.score))
|
posts = posts.filter(Post.posted_at > utcnow() - timedelta(days=1)).order_by(desc(Post.score))
|
||||||
elif sort == 'new':
|
elif sort == 'new':
|
||||||
posts = posts.order_by(desc(Post.posted_at))
|
posts = posts.order_by(desc(Post.posted_at))
|
||||||
|
elif sort == 'active':
|
||||||
|
posts = posts.order_by(desc(Post.last_active))
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
posts = posts.paginate(page=page, per_page=100, error_out=False)
|
posts = posts.paginate(page=page, per_page=100, error_out=False)
|
||||||
|
@ -111,7 +116,7 @@ def home_page(type, sort='hot'):
|
||||||
POST_TYPE_IMAGE=POST_TYPE_IMAGE, POST_TYPE_LINK=POST_TYPE_LINK,
|
POST_TYPE_IMAGE=POST_TYPE_IMAGE, POST_TYPE_LINK=POST_TYPE_LINK,
|
||||||
low_bandwidth=request.cookies.get('low_bandwidth', '0') == '1',
|
low_bandwidth=request.cookies.get('low_bandwidth', '0') == '1',
|
||||||
SUBSCRIPTION_PENDING=SUBSCRIPTION_PENDING, SUBSCRIPTION_MEMBER=SUBSCRIPTION_MEMBER,
|
SUBSCRIPTION_PENDING=SUBSCRIPTION_PENDING, SUBSCRIPTION_MEMBER=SUBSCRIPTION_MEMBER,
|
||||||
etag=f"{type}_{hash(str(g.site.last_active))}", next_url=next_url, prev_url=prev_url,
|
etag=f"{type}_{sort}_{hash(str(g.site.last_active))}", next_url=next_url, prev_url=prev_url,
|
||||||
rss_feed=f"https://{current_app.config['SERVER_NAME']}/feed",
|
rss_feed=f"https://{current_app.config['SERVER_NAME']}/feed",
|
||||||
rss_feed_name=f"Posts on " + g.site.name,
|
rss_feed_name=f"Posts on " + g.site.name,
|
||||||
title=f"{g.site.name} - {g.site.description}",
|
title=f"{g.site.name} - {g.site.description}",
|
||||||
|
|
|
@ -343,6 +343,7 @@ class User(UserMixin, db.Model):
|
||||||
ip_address = db.Column(db.String(50))
|
ip_address = db.Column(db.String(50))
|
||||||
instance_id = db.Column(db.Integer, db.ForeignKey('instance.id'), index=True)
|
instance_id = db.Column(db.Integer, db.ForeignKey('instance.id'), index=True)
|
||||||
reports = db.Column(db.Integer, default=0) # how many times this user has been reported.
|
reports = db.Column(db.Integer, default=0) # how many times this user has been reported.
|
||||||
|
default_sort = db.Column(db.String(25), default='hot')
|
||||||
|
|
||||||
avatar = db.relationship('File', lazy='joined', foreign_keys=[avatar_id], single_parent=True, cascade="all, delete-orphan")
|
avatar = db.relationship('File', lazy='joined', foreign_keys=[avatar_id], single_parent=True, cascade="all, delete-orphan")
|
||||||
cover = db.relationship('File', lazy='joined', foreign_keys=[cover_id], single_parent=True, cascade="all, delete-orphan")
|
cover = db.relationship('File', lazy='joined', foreign_keys=[cover_id], single_parent=True, cascade="all, delete-orphan")
|
||||||
|
|
|
@ -8,4 +8,7 @@
|
||||||
<a href="/{{ type }}/new" class="btn {{ 'btn-primary' if sort == 'new' else 'btn-outline-secondary' }}" rel="nofollow">
|
<a href="/{{ type }}/new" class="btn {{ 'btn-primary' if sort == 'new' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
{{ _('New') }}
|
{{ _('New') }}
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/{{ type }}/active" class="btn {{ 'btn-primary' if sort == 'active' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
|
{{ _('Active') }}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
|
@ -2,13 +2,16 @@
|
||||||
<a class="btn btn-primary" href="/community/{{ community.link() }}/submit">{{ _('Create post') }}</a>
|
<a class="btn btn-primary" href="/community/{{ community.link() }}/submit">{{ _('Create post') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group mt-1 mb-2">
|
<div class="btn-group mt-1 mb-2">
|
||||||
<a href="?sort=hot" class="btn {{ 'btn-primary' if request.args.get('sort', '') == '' or request.args.get('sort', '') == 'hot' else 'btn-outline-secondary' }}" rel="nofollow">
|
<a href="?sort=hot" class="btn {{ 'btn-primary' if sort == '' or sort == 'hot' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
{{ _('Hot') }}
|
{{ _('Hot') }}
|
||||||
</a>
|
</a>
|
||||||
<a href="?sort=top" class="btn {{ 'btn-primary' if request.args.get('sort', '') == 'top' else 'btn-outline-secondary' }}" rel="nofollow">
|
<a href="?sort=top" class="btn {{ 'btn-primary' if sort == 'top' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
{{ _('Top') }}
|
{{ _('Top') }}
|
||||||
</a>
|
</a>
|
||||||
<a href="?sort=new" class="btn {{ 'btn-primary' if request.args.get('sort', '') == 'new' else 'btn-outline-secondary' }}" rel="nofollow">
|
<a href="?sort=new" class="btn {{ 'btn-primary' if sort == 'new' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
{{ _('New') }}
|
{{ _('New') }}
|
||||||
</a>
|
</a>
|
||||||
|
<a href="?sort=active" class="btn {{ 'btn-primary' if sort == 'active' else 'btn-outline-secondary' }}" rel="nofollow">
|
||||||
|
{{ _('Active') }}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
|
@ -20,6 +20,7 @@
|
||||||
{{ render_field(form.nsfl) }}
|
{{ render_field(form.nsfl) }}
|
||||||
{{ render_field(form.searchable) }}
|
{{ render_field(form.searchable) }}
|
||||||
{{ render_field(form.indexable) }}
|
{{ render_field(form.indexable) }}
|
||||||
|
{{ render_field(form.default_sort) }}
|
||||||
{{ render_field(form.import_file) }}
|
{{ render_field(form.import_file) }}
|
||||||
{{ render_field(form.submit) }}
|
{{ render_field(form.submit) }}
|
||||||
<a href="{{ url_for('user.user_settings_filters') }}">{{ _('Manage content filters') }}</a>
|
<a href="{{ url_for('user.user_settings_filters') }}">{{ _('Manage content filters') }}</a>
|
||||||
|
|
|
@ -2,7 +2,7 @@ from flask import session
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import StringField, SubmitField, PasswordField, BooleanField, EmailField, TextAreaField, FileField, \
|
from wtforms import StringField, SubmitField, PasswordField, BooleanField, EmailField, TextAreaField, FileField, \
|
||||||
RadioField, DateField
|
RadioField, DateField, SelectField
|
||||||
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo, Length, Optional
|
||||||
from flask_babel import _, lazy_gettext as _l
|
from flask_babel import _, lazy_gettext as _l
|
||||||
|
|
||||||
|
@ -35,6 +35,12 @@ class SettingsForm(FlaskForm):
|
||||||
indexable = BooleanField(_l('Allow search engines to index this profile'))
|
indexable = BooleanField(_l('Allow search engines to index this profile'))
|
||||||
manually_approves_followers = BooleanField(_l('Manually approve followers'))
|
manually_approves_followers = BooleanField(_l('Manually approve followers'))
|
||||||
import_file = FileField(_('Import community subscriptions and user blocks from Lemmy'))
|
import_file = FileField(_('Import community subscriptions and user blocks from Lemmy'))
|
||||||
|
sorts = [('hot', _l('Hot')),
|
||||||
|
('top', _l('Top')),
|
||||||
|
('new', _l('New')),
|
||||||
|
('active', _l('Active')),
|
||||||
|
]
|
||||||
|
default_sort = SelectField(_l('By default, sort posts by'), choices=sorts, validators=[DataRequired()], coerce=str)
|
||||||
submit = SubmitField(_l('Save settings'))
|
submit = SubmitField(_l('Save settings'))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,7 @@ def change_settings():
|
||||||
current_user.show_nsfl = form.nsfl.data
|
current_user.show_nsfl = form.nsfl.data
|
||||||
current_user.searchable = form.searchable.data
|
current_user.searchable = form.searchable.data
|
||||||
current_user.indexable = form.indexable.data
|
current_user.indexable = form.indexable.data
|
||||||
|
current_user.default_sort = form.default_sort.data
|
||||||
import_file = request.files['import_file']
|
import_file = request.files['import_file']
|
||||||
if import_file and import_file.filename != '':
|
if import_file and import_file.filename != '':
|
||||||
file_ext = os.path.splitext(import_file.filename)[1]
|
file_ext = os.path.splitext(import_file.filename)[1]
|
||||||
|
@ -187,6 +188,7 @@ def change_settings():
|
||||||
form.nsfl.data = current_user.show_nsfl
|
form.nsfl.data = current_user.show_nsfl
|
||||||
form.searchable.data = current_user.searchable
|
form.searchable.data = current_user.searchable
|
||||||
form.indexable.data = current_user.indexable
|
form.indexable.data = current_user.indexable
|
||||||
|
form.default_sort.data = current_user.default_sort
|
||||||
|
|
||||||
return render_template('user/edit_settings.html', title=_('Edit profile'), form=form, user=current_user,
|
return render_template('user/edit_settings.html', title=_('Edit profile'), form=form, user=current_user,
|
||||||
moderating_communities=moderating_communities(current_user.get_id()),
|
moderating_communities=moderating_communities(current_user.get_id()),
|
||||||
|
|
32
migrations/versions/b86c49cbd9a0_default_sort.py
Normal file
32
migrations/versions/b86c49cbd9a0_default_sort.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
"""default sort
|
||||||
|
|
||||||
|
Revision ID: b86c49cbd9a0
|
||||||
|
Revises: 8885aafd5291
|
||||||
|
Create Date: 2024-01-15 17:37:17.886232
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'b86c49cbd9a0'
|
||||||
|
down_revision = '8885aafd5291'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('default_sort', sa.String(length=25), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('default_sort')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in a new issue