Add pagination to subscriptions page

This commit is contained in:
James Taylor 2019-08-12 01:14:11 -07:00
parent c55955f42d
commit dd4841901f
2 changed files with 44 additions and 18 deletions

View File

@ -11,6 +11,7 @@ import traceback
import contextlib import contextlib
import defusedxml.ElementTree import defusedxml.ElementTree
import urllib import urllib
import math
import flask import flask
from flask import request from flask import request
@ -121,7 +122,16 @@ def _unsubscribe(cursor, channel_ids):
gevent.spawn(delete_thumbnails, to_delete) gevent.spawn(delete_thumbnails, to_delete)
cursor.executemany("DELETE FROM subscribed_channels WHERE yt_channel_id=?", ((channel_id, ) for channel_id in channel_ids)) cursor.executemany("DELETE FROM subscribed_channels WHERE yt_channel_id=?", ((channel_id, ) for channel_id in channel_ids))
def _get_videos(cursor, number, offset, tag = None): def _get_videos(cursor, number_per_page, offset, tag = None):
'''Returns a full page of videos with an offset, and a value good enough to be used as the total number of videos'''
# We ask for the next 9 pages from the database
# Then the actual length of the results tell us if there are more than 9 pages left, and if not, how many there actually are
# This is done since there are only 9 page buttons on display at a time
# If there are more than 9 pages left, we give a fake value in place of the real number of results if the entire database was queried without limit
# This fake value is sufficient to get the page button generation macro to display 9 page buttons
# If we wish to display more buttons this logic must change
# We cannot use tricks with the sql id for the video since we frequently have filters and other restrictions in place on the results anyway
# TODO: This is probably not the ideal solution
if tag is not None: if tag is not None:
db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name
FROM videos FROM videos
@ -129,21 +139,29 @@ def _get_videos(cursor, number, offset, tag = None):
INNER JOIN tag_associations on videos.sql_channel_id = tag_associations.sql_channel_id INNER JOIN tag_associations on videos.sql_channel_id = tag_associations.sql_channel_id
WHERE tag = ? WHERE tag = ?
ORDER BY time_published DESC ORDER BY time_published DESC
LIMIT ? OFFSET ?''', (tag, number, offset)) LIMIT ? OFFSET ?''', (tag, number_per_page*9, offset)).fetchall()
else: else:
db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name db_videos = cursor.execute('''SELECT video_id, title, duration, channel_name
FROM videos FROM videos
INNER JOIN subscribed_channels on videos.sql_channel_id = subscribed_channels.id INNER JOIN subscribed_channels on videos.sql_channel_id = subscribed_channels.id
ORDER BY time_published DESC ORDER BY time_published DESC
LIMIT ? OFFSET ?''', (number, offset)) LIMIT ? OFFSET ?''', (number_per_page*9, offset)).fetchall()
for db_video in db_videos: pseudo_number_of_videos = offset + len(db_videos)
yield {
videos = []
for db_video in db_videos[0:number_per_page]:
videos.append({
'id': db_video[0], 'id': db_video[0],
'title': db_video[1], 'title': db_video[1],
'duration': db_video[2], 'duration': db_video[2],
'author': db_video[3], 'author': db_video[3],
} })
return videos, pseudo_number_of_videos
def _get_subscribed_channels(cursor): def _get_subscribed_channels(cursor):
for item in cursor.execute('''SELECT channel_name, yt_channel_id, muted for item in cursor.execute('''SELECT channel_name, yt_channel_id, muted
@ -489,16 +507,16 @@ def post_subscription_manager_page():
@yt_app.route('/subscriptions', methods=['GET']) @yt_app.route('/subscriptions', methods=['GET'])
@yt_app.route('/feed/subscriptions', methods=['GET']) @yt_app.route('/feed/subscriptions', methods=['GET'])
def get_subscriptions_page(): def get_subscriptions_page():
page = int(request.args.get('page', 1))
with open_database() as connection: with open_database() as connection:
with connection as cursor: with connection as cursor:
tag = request.args.get('tag', None) tag = request.args.get('tag', None)
videos = [] videos, number_of_videos_in_db = _get_videos(cursor, 60, (page - 1)*60, tag)
for video in _get_videos(cursor, 60, 0, tag): for video in videos:
video['thumbnail'] = util.URL_ORIGIN + '/data/subscription_thumbnails/' + video['id'] + '.jpg' video['thumbnail'] = util.URL_ORIGIN + '/data/subscription_thumbnails/' + video['id'] + '.jpg'
video['type'] = 'video' video['type'] = 'video'
video['item_size'] = 'small' video['item_size'] = 'small'
yt_data_extract.add_extra_html_info(video) yt_data_extract.add_extra_html_info(video)
videos.append(video)
tags = _get_all_tags(cursor) tags = _get_all_tags(cursor)
@ -514,6 +532,8 @@ def get_subscriptions_page():
return flask.render_template('subscriptions.html', return flask.render_template('subscriptions.html',
videos = videos, videos = videos,
num_pages = math.ceil(number_of_videos_in_db/60),
parameters_dictionary = request.args,
tags = tags, tags = tags,
subscription_list = subscription_list, subscription_list = subscription_list,
) )

View File

@ -7,9 +7,12 @@
display:flex; display:flex;
flex-direction: row; flex-direction: row;
} }
.item-grid{ .video-section{
flex-grow: 1; flex-grow: 1;
} }
.video-section .page-button-row{
justify-content: center;
}
.subscriptions-sidebar{ .subscriptions-sidebar{
flex-basis: 300px; flex-basis: 300px;
background-color: #dadada; background-color: #dadada;
@ -44,12 +47,18 @@
{% endblock style %} {% endblock style %}
{% block main %} {% block main %}
<div class="video-section">
<nav class="item-grid"> <nav class="item-grid">
{% for video_info in videos %} {% for video_info in videos %}
{{ common_elements.item(video_info, include_author=false) }} {{ common_elements.item(video_info, include_author=false) }}
{% endfor %} {% endfor %}
</nav> </nav>
<nav class="page-button-row">
{{ common_elements.page_buttons(num_pages, '/youtube.com/subscriptions', parameters_dictionary) }}
</nav>
</div>
<div class="subscriptions-sidebar"> <div class="subscriptions-sidebar">
<div class="sidebar-links"> <div class="sidebar-links">
<a href="/youtube.com/subscription_manager" class="sub-manager-link">Subscription Manager</a> <a href="/youtube.com/subscription_manager" class="sub-manager-link">Subscription Manager</a>
@ -91,7 +100,4 @@
</div> </div>
<nav class="page-button-row">
{# TODO #}
</nav>
{% endblock main %} {% endblock main %}