mirror of https://gitlab.com/bashrc2/epicyon
Display list of recent books on profiles
parent
6c56b786eb
commit
f1220b8497
|
|
@ -257,6 +257,36 @@ body, html {
|
||||||
image-rendering: var(--rendering);
|
image-rendering: var(--rendering);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
book_list_section {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
book_list {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
list-style: none;
|
||||||
|
margin: 1rem 0;
|
||||||
|
overflow-x: scroll;
|
||||||
|
padding: 0 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
book_event {
|
||||||
|
padding: 0 1rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
book_span {
|
||||||
|
}
|
||||||
|
|
||||||
|
book_span_div {
|
||||||
|
border-radius: 9px;
|
||||||
|
height: 30vw;
|
||||||
|
width: 20vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
book_image_div {
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: var(--code-color);
|
color: var(--code-color);
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
|
|
|
||||||
113
reading.py
113
reading.py
|
|
@ -9,6 +9,7 @@ __module_group__ = "Core"
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from collections import OrderedDict
|
||||||
from utils import get_content_from_post
|
from utils import get_content_from_post
|
||||||
from utils import has_object_dict
|
from utils import has_object_dict
|
||||||
from utils import remove_id_ending
|
from utils import remove_id_ending
|
||||||
|
|
@ -196,19 +197,20 @@ def _add_book_to_reader(reader_books_json: {}, book_dict: {}) -> None:
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
reader_books_json[book_url][book_event_type] = book_dict
|
reader_books_json[book_url][book_event_type] = book_dict
|
||||||
if book_dict.get('published'):
|
if not book_dict.get('published'):
|
||||||
if 'timeline' not in reader_books_json:
|
return
|
||||||
reader_books_json['timeline'] = {}
|
if 'timeline' not in reader_books_json:
|
||||||
published = book_dict['published']
|
reader_books_json['timeline'] = {}
|
||||||
if book_dict.get('updated'):
|
published = book_dict['published']
|
||||||
published = book_dict['updated']
|
if book_dict.get('updated'):
|
||||||
post_time_object = \
|
published = book_dict['updated']
|
||||||
date_from_string_format(published, ["%Y-%m-%dT%H:%M:%S%z"])
|
post_time_object = \
|
||||||
if post_time_object:
|
date_from_string_format(published, ["%Y-%m-%dT%H:%M:%S%z"])
|
||||||
baseline_time = date_epoch()
|
if post_time_object:
|
||||||
days_diff = post_time_object - baseline_time
|
baseline_time = date_epoch()
|
||||||
post_days_since_epoch = days_diff.days
|
days_diff = post_time_object - baseline_time
|
||||||
reader_books_json['timeline'][post_days_since_epoch] = book_url
|
post_days_since_epoch = days_diff.days
|
||||||
|
reader_books_json['timeline'][post_days_since_epoch] = book_url
|
||||||
|
|
||||||
|
|
||||||
def _add_reader_to_book(book_json: {}, book_dict: {}) -> None:
|
def _add_reader_to_book(book_json: {}, book_dict: {}) -> None:
|
||||||
|
|
@ -357,3 +359,88 @@ def store_book_events(base_dir: str,
|
||||||
_deduplicate_recent_books_list(base_dir, max_recent_books)
|
_deduplicate_recent_books_list(base_dir, max_recent_books)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def html_profile_book_list(base_dir: str, actor: str, no_of_books: int,
|
||||||
|
translate: {}) -> str:
|
||||||
|
"""Returns html for displaying a list of books on a profile screen
|
||||||
|
"""
|
||||||
|
reading_path = base_dir + '/accounts/reading'
|
||||||
|
readers_path = reading_path + '/readers'
|
||||||
|
reader_books_filename = \
|
||||||
|
readers_path + '/' + actor.replace('/', '#') + '.json'
|
||||||
|
reader_books_json = {}
|
||||||
|
if not os.path.isfile(reader_books_filename):
|
||||||
|
return ''
|
||||||
|
reader_books_json = load_json(reader_books_filename)
|
||||||
|
if not reader_books_json.get('timeline'):
|
||||||
|
return ''
|
||||||
|
# sort the timeline in descending order
|
||||||
|
recent_books_json = \
|
||||||
|
OrderedDict(sorted(reader_books_json['timeline'].items(),
|
||||||
|
reverse=True))
|
||||||
|
html_str = '<div class="book_list_section">\n'
|
||||||
|
html_str += ' <ul class="book_list">\n'
|
||||||
|
ctr = 0
|
||||||
|
for _, book_url in recent_books_json.items():
|
||||||
|
if not reader_books_json.get(book_url):
|
||||||
|
continue
|
||||||
|
book_rating = None
|
||||||
|
book_wanted = False
|
||||||
|
book_finished = False
|
||||||
|
for event_type in ('want', 'finished', 'rated'):
|
||||||
|
if not reader_books_json[book_url].get(event_type):
|
||||||
|
continue
|
||||||
|
book_dict = reader_books_json[book_url][event_type]
|
||||||
|
if book_dict.get('name'):
|
||||||
|
book_title = book_dict['name']
|
||||||
|
if book_dict.get('image_url'):
|
||||||
|
book_image_url = book_dict['image_url']
|
||||||
|
if event_type == 'rated':
|
||||||
|
book_rating = book_dict['rating']
|
||||||
|
elif event_type == 'want':
|
||||||
|
book_wanted = True
|
||||||
|
elif event_type == 'finished':
|
||||||
|
book_finished = True
|
||||||
|
if book_title and book_image_url:
|
||||||
|
book_title = remove_html(book_title)
|
||||||
|
html_str += ' <li class="book_event">\n'
|
||||||
|
html_str += ' <span class="book_span">\n'
|
||||||
|
html_str += ' <div class="book_span_div">\n'
|
||||||
|
|
||||||
|
# book image
|
||||||
|
html_str += ' <a href="' + book_url + \
|
||||||
|
'" target="_blank" rel="nofollow noopener noreferrer">\n'
|
||||||
|
html_str += ' <div class="book_image_div">\n'
|
||||||
|
html_str += ' <img src="' + book_image_url + '" ' + \
|
||||||
|
'alt="' + book_title + '">\n'
|
||||||
|
html_str += ' </div>\n'
|
||||||
|
html_str += ' </a>\n'
|
||||||
|
|
||||||
|
# book details
|
||||||
|
html_str += ' <div class="book_details_div">\n'
|
||||||
|
html_str += ' <a href="' + book_url + \
|
||||||
|
'" target="_blank" rel="nofollow noopener noreferrer">\n'
|
||||||
|
html_str += ' <b>' + book_title.title() + '</b></a>\n'
|
||||||
|
if book_finished:
|
||||||
|
html_str += ' <br>' + \
|
||||||
|
translate['finished reading'].title() + '\n'
|
||||||
|
if book_wanted:
|
||||||
|
html_str += ' <br>' + \
|
||||||
|
translate['Wanted'] + '\n'
|
||||||
|
if book_rating is not None:
|
||||||
|
html_str += ' <br>'
|
||||||
|
for _ in range(int(book_rating)):
|
||||||
|
html_str += '⭐'
|
||||||
|
html_str += ' (' + str(book_rating) + ')'
|
||||||
|
html_str += ' </div>\n'
|
||||||
|
|
||||||
|
html_str += ' </div>\n'
|
||||||
|
html_str += ' </span>\n'
|
||||||
|
html_str += ' </li>\n'
|
||||||
|
ctr += 1
|
||||||
|
if ctr >= no_of_books:
|
||||||
|
break
|
||||||
|
html_str += ' </ul>\n'
|
||||||
|
html_str += '</div>\n'
|
||||||
|
return html_str
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ from session import site_is_verified
|
||||||
from session import get_json
|
from session import get_json
|
||||||
from shares import actor_attached_shares_as_html
|
from shares import actor_attached_shares_as_html
|
||||||
from git import get_repo_url
|
from git import get_repo_url
|
||||||
|
from reading import html_profile_book_list
|
||||||
|
|
||||||
THEME_FORMATS = '.zip, .gz'
|
THEME_FORMATS = '.zip, .gz'
|
||||||
BLOCKFILE_FORMATS = '.csv'
|
BLOCKFILE_FORMATS = '.csv'
|
||||||
|
|
@ -397,7 +398,8 @@ def html_profile_after_search(authorized: bool,
|
||||||
attached_shared_items,
|
attached_shared_items,
|
||||||
website_url, repo_url,
|
website_url, repo_url,
|
||||||
send_blocks_str,
|
send_blocks_str,
|
||||||
authorized)
|
authorized,
|
||||||
|
person_url)
|
||||||
|
|
||||||
domain_full = get_full_domain(domain, port)
|
domain_full = get_full_domain(domain, port)
|
||||||
|
|
||||||
|
|
@ -580,7 +582,8 @@ def _get_profile_header(base_dir: str, http_prefix: str, nickname: str,
|
||||||
access_keys: {},
|
access_keys: {},
|
||||||
joined_date: str,
|
joined_date: str,
|
||||||
occupation_name: str,
|
occupation_name: str,
|
||||||
actor_proxied: str) -> str:
|
actor_proxied: str,
|
||||||
|
person_url: str) -> str:
|
||||||
"""The header of the profile screen, containing background
|
"""The header of the profile screen, containing background
|
||||||
image and avatar
|
image and avatar
|
||||||
"""
|
"""
|
||||||
|
|
@ -708,6 +711,9 @@ def _get_profile_header(base_dir: str, http_prefix: str, nickname: str,
|
||||||
html_str += \
|
html_str += \
|
||||||
' </figcaption>\n' + \
|
' </figcaption>\n' + \
|
||||||
' </figure>\n\n'
|
' </figure>\n\n'
|
||||||
|
|
||||||
|
# book events for this actor
|
||||||
|
html_str += html_profile_book_list(base_dir, person_url, 5, translate)
|
||||||
return html_str
|
return html_str
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -732,7 +738,8 @@ def _get_profile_header_after_search(base_dir: str,
|
||||||
website_url: str,
|
website_url: str,
|
||||||
repo_url: str,
|
repo_url: str,
|
||||||
send_blocks_str: str,
|
send_blocks_str: str,
|
||||||
authorized: bool) -> str:
|
authorized: bool,
|
||||||
|
person_url: str) -> str:
|
||||||
"""The header of a searched for handle, containing background
|
"""The header of a searched for handle, containing background
|
||||||
image and avatar
|
image and avatar
|
||||||
"""
|
"""
|
||||||
|
|
@ -857,6 +864,8 @@ def _get_profile_header_after_search(base_dir: str,
|
||||||
html_str += \
|
html_str += \
|
||||||
_profile_shared_items_list(attached_shared_items,
|
_profile_shared_items_list(attached_shared_items,
|
||||||
translate)
|
translate)
|
||||||
|
# book events for this actor
|
||||||
|
html_str += html_profile_book_list(base_dir, person_url, 5, translate)
|
||||||
|
|
||||||
return html_str
|
return html_str
|
||||||
|
|
||||||
|
|
@ -1248,7 +1257,7 @@ def html_profile(signing_priv_key_pem: str,
|
||||||
attached_shared_items,
|
attached_shared_items,
|
||||||
access_keys, joined_date,
|
access_keys, joined_date,
|
||||||
occupation_name,
|
occupation_name,
|
||||||
actor_proxied)
|
actor_proxied, actor)
|
||||||
|
|
||||||
# keyboard navigation
|
# keyboard navigation
|
||||||
user_path_str = '/users/' + nickname
|
user_path_str = '/users/' + nickname
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue