From b4f1330df338609f54c8aed23847640331f696ea Mon Sep 17 00:00:00 2001 From: Alex Schlumpf Date: Tue, 18 Feb 2020 22:00:45 -0500 Subject: [PATCH] remove all garbage files --- .gitignore | 2 + gutenbergtozim/database.py | 4 +- gutenbergtozim/download.py | 19 ++- gutenbergtozim/export.py | 41 ++--- gutenbergtozim/l10n.py | 6 +- gutenbergtozim/rdf.py | 9 +- gutenbergtozim/templates/base.html | 26 ++- gutenbergtozim/templates/bookshelf.html | 9 + gutenbergtozim/templates/cover_article.html | 8 +- gutenbergtozim/templates/css/style.css | 52 ++++++ gutenbergtozim/templates/js/tools.js | 173 ++++++++++++++++++++ 11 files changed, 295 insertions(+), 54 deletions(-) create mode 100644 gutenbergtozim/templates/bookshelf.html diff --git a/.gitignore b/.gitignore index f2cddf7..09df7e0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ __pycache__/ *.so # Distribution / packaging +.vscode/ +gut-env/ .Python env/ venv/ diff --git a/gutenbergtozim/database.py b/gutenbergtozim/database.py index 610a4de..3aa41f6 100644 --- a/gutenbergtozim/database.py +++ b/gutenbergtozim/database.py @@ -137,6 +137,7 @@ class Meta: language = CharField(max_length=10) downloads = IntegerField(default=0) bookshelf = CharField(max_length=500, null=True) + cover_page = IntegerField(default=0) popularity = 0 @@ -150,7 +151,8 @@ def to_dict(self): 'license': self.license, 'language': self.language, 'downloads': self.downloads, - 'bookshelf': self.bookshelf} + 'bookshelf': self.bookshelf, + 'cover_page': self.cover_page} def to_array(self): fmts = self.formats() diff --git a/gutenbergtozim/download.py b/gutenbergtozim/download.py index 2265552..191d1d7 100644 --- a/gutenbergtozim/download.py +++ b/gutenbergtozim/download.py @@ -15,10 +15,11 @@ from gutenbergtozim import logger, TMP_FOLDER from gutenbergtozim.urls import get_urls -from gutenbergtozim.database import BookFormat, Format +from gutenbergtozim.database import BookFormat, Format, Book from gutenbergtozim.export import get_list_of_filtered_books, fname_for from gutenbergtozim.utils import download_file, FORMAT_MATRIX, ensure_unicode +IMAGE_BASE = 'http://aleph.gutenberg.org/cache/epub/' def resource_exists(url): r = requests.get(url, stream=True, timeout=20) # in seconds @@ -212,6 +213,19 @@ def download_book(book, download_cache, languages, formats, force): continue +def download_covers(book,download_cache): + cover = '{}_cover.jpg'.format(book.id) + fpath = os.path.join(download_cache, cover) + has_cover = Book.select(Book.cover_page).where( Book.id == book.id) + if has_cover: + title = '{}{}/pg{}.cover.medium.jpg'.format(IMAGE_BASE,book.id,book.id) + logger.debug('Downloading {}'.format(title)) + download_file(title,fpath) + else: + logger.debug('No Book Cover found for Book #{}'.format(book.id)) + return True + + def download_all_books(download_cache, concurrency, languages=[], formats=[], only_books=[], force=False): @@ -225,4 +239,7 @@ def download_all_books(download_cache, concurrency, def dlb(b): return download_book(b, download_cache, languages, formats, force) + def dlb_covers(b): + return download_covers(b,download_cache) Pool(concurrency).map(dlb, available_books) + Pool(concurrency).map(dlb_covers,available_books) \ No newline at end of file diff --git a/gutenbergtozim/export.py b/gutenbergtozim/export.py index 54c1878..e0669f7 100644 --- a/gutenbergtozim/export.py +++ b/gutenbergtozim/export.py @@ -132,7 +132,6 @@ def export_skeleton(static_folder, dev_mode=False, rendered = template.render(**context) save_bs_output(rendered, os.path.join(static_folder, tpl_path), UTF8) - def export_all_books(static_folder, download_cache, concurrency, @@ -798,36 +797,6 @@ def dumpjs(col, fn, var='json_data'): dumpjs([author.to_array() for author in authors], 'authors_lang_{}.js'.format(lang), 'authors_json_data') - - # TODO refactor so author and bookshelves call the same function - # TODO make separate Bookshelves by language - # Bookshelf specific collections - # bookshelves = bookshelf_list() - # all_bookshelves = [] - # for bookshelf in bookshelves: - # if bookshelf == None: - # continue - # bookshelf_object = {} - # bookshelf_object["name"] = bookshelf - # bookshelf_object["by_popularity"] = [ - # book.to_array() - # for book in Book.select().where(Book.bookshelf == bookshelf) - # .order_by(Book.downloads.desc()) - # ] - # bookshelf_object["by_title"] = [ - # book.to_array() - # for book in Book.select().where(Book.bookshelf == bookshelf) - # .order_by(Book.title.asc()) - # ] - # all_bookshelves += [bookshelf_object] - # logger.info('\t\tDumping bookshelves.js') - # dumpjs(all_bookshelves, 'bookshelves.js', 'bookshelves_json_data') - # context = get_default_context(project_id=project_id, books=books) - # context.update({'bookshelves':all_bookshelves}) - # template = jinja_env.get_template('bookshelf_home.html') - # rendered = template.render(**context) - # save_bs_output(rendered, os.path.join(static_folder, 'bookshelf_home.html'), UTF8) - bookshelves = bookshelf_list() for bookshelf in bookshelves: #exclude the books with no bookshelf data @@ -880,6 +849,16 @@ def dumpjs(col, fn, var='json_data'): template = jinja_env.get_template('bookshelf_home.html') rendered = template.render(**context) save_bs_output(rendered, os.path.join(static_folder, 'bookshelf_home.html'), UTF8) + + # add individual bookshelf pages + for header in bookshelves: + for bookshelf in header: + context["bookshelf"] = bookshelf + template = jinja_env.get_template('bookshelf.html') + rendered = template.render(**context) + savepath = os.path.join(static_folder, "{}.html".format(bookshelf)) + # logger.info("Saving {} to {}".format(bookshelf, savepath)) + save_bs_output(rendered, savepath, UTF8) # Won't need this if you do the templating for bookshelf_home here # bookshelf list sorted by name diff --git a/gutenbergtozim/l10n.py b/gutenbergtozim/l10n.py index 87559b6..fbd58d7 100644 --- a/gutenbergtozim/l10n.py +++ b/gutenbergtozim/l10n.py @@ -30,7 +30,11 @@ }, "author": { "textContent": "Author", - "placeholder": "List books of a single Author" + "placeholder": "Search by author name" + }, + "title": { + "textContext": "Title", + "placeholder": "Search by title" }, "cover-img": { "alt": "Book Cover", diff --git a/gutenbergtozim/rdf.py b/gutenbergtozim/rdf.py index f134828..397f327 100644 --- a/gutenbergtozim/rdf.py +++ b/gutenbergtozim/rdf.py @@ -119,6 +119,7 @@ def __init__(self, rdf_data, gid): self.last_name = None self.bookshelf = None + self.cover_image = 0 def parse(self): soup = BeautifulSoup(self.rdf_data, "lxml") @@ -138,6 +139,11 @@ def parse(self): if self.bookshelf: self.bookshelf = self.bookshelf.find('rdf:value').text + #Search rdf to see if the image exists at the hard link + #https://www.gutenberg.ord/cache/epub/id/pg{id}.cover.medium.jpg + if soup.find('cover.medium.jpg'): + self.cover_image = 1 + # Parsing the name of the Author. Sometimes it's the name of # an organization or the name is not known and therefore # the or node only return @@ -246,7 +252,8 @@ def save_rdf_in_database(parser): license=license_record, # foreign key language=parser.language.strip(), downloads=parser.downloads, - bookshelf=parser.bookshelf + bookshelf=parser.bookshelf, + cover_image=parser.cover_image ) else: book_record.title = normalize(parser.title.strip()) diff --git a/gutenbergtozim/templates/base.html b/gutenbergtozim/templates/base.html index 8e4f84a..c50cdde 100644 --- a/gutenbergtozim/templates/base.html +++ b/gutenbergtozim/templates/base.html @@ -52,17 +52,18 @@

The first producer of free eboo diff --git a/gutenbergtozim/templates/bookshelf.html b/gutenbergtozim/templates/bookshelf.html new file mode 100644 index 0000000..86c28cf --- /dev/null +++ b/gutenbergtozim/templates/bookshelf.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% block title %}Individual Bookshelf{% endblock %} +{% block content %} +

{{ bookshelf }} Bookshelf

+
+ +{% endblock %} diff --git a/gutenbergtozim/templates/cover_article.html b/gutenbergtozim/templates/cover_article.html index 1fe7398..fe8f4f8 100644 --- a/gutenbergtozim/templates/cover_article.html +++ b/gutenbergtozim/templates/cover_article.html @@ -8,16 +8,16 @@

{{ book.subtitle }}

{% if cover_img %} -
+
Book Cover
-
+ {% endif %} diff --git a/gutenbergtozim/templates/css/style.css b/gutenbergtozim/templates/css/style.css index 2d6b126..f972eb5 100644 --- a/gutenbergtozim/templates/css/style.css +++ b/gutenbergtozim/templates/css/style.css @@ -239,6 +239,22 @@ dataTables_wrapper.dataTables_length, overflow-y: auto; } +.nav-link { + text-decoration: underline; + cursor: pointer; +} + +.filter-container { + width: 100%; + display: block; + margin: auto; +} + +.filter-container .pure-input-rounded { + margin-bottom: 0.5em !important; + display: inherit !important; +} + /*.ui-menu-item, .ui-menu-item:hover, .ui-menu-item:link, @@ -373,6 +389,24 @@ body.cover .content h2 { margin: 0 auto; } +.bookshelves { + display: block; + margin: auto; +} + +.bookshelves__list { + margin: 10px 0px; +} + +.bookshelves__list--header { + font-size: 24px; + text-align: center; +} + +.bookshelves__list--bookshelf { + text-align: center; +} + /* mobile */ @media(max-width:768px) { @@ -509,7 +543,25 @@ body.cover .content h2 { #author_filter.clearable.onX{ cursor: pointer; } /* (jQ) hover cursor style */ #author_filter.clearable::-ms-clear {display: none; width:0; height:0;} /* Remove IE default X */ +#title_filter.clearable{ + background: #fff url(data:image/gif;base64,R0lGODlhBwAHAIAAAP///5KSkiH5BAAAAAAALAAAAAAHAAcAAAIMTICmsGrIXnLxuDMLADs=) no-repeat right -1em center; + /*border: 1px solid #999; + padding: 3px 18px 3px 4px; Use the same right padding (18) in jQ! + border-radius: 3px;*/ + transition: background 0.4s; + } +#title_filter.clearable.x { background-position: right 1em center; } /* (jQ) Show icon */ +#title_filter.clearable.onX{ cursor: pointer; } /* (jQ) hover cursor style */ +#title_filter.clearable::-ms-clear {display: none; width:0; height:0;} /* Remove IE default X */ + +/* @media (max-width: 1400px) { + +} */ + @media (max-width: 800px) { + .nav-link { + text-align: center; + } .fa-download { display: none; } diff --git a/gutenbergtozim/templates/js/tools.js b/gutenbergtozim/templates/js/tools.js index a3fe53c..e9b18fd 100644 --- a/gutenbergtozim/templates/js/tools.js +++ b/gutenbergtozim/templates/js/tools.js @@ -366,6 +366,178 @@ function showBooks() { console.log('after populateFilters'); } +function showBookshelf(bookshelfURL) { + console.log('showBookshelf'); + /* Show spinner if loading takes more than 1 second */ + inBooksLoadingLoop = true; + setTimeout(function() { + if (inBooksLoadingLoop) { + $('#spinner').show(); + } + }, 1000); + + populateFilters(function() { + console.log('populateFilters callback'); + + // redirect to home page + // if (is_cover_page()) { + // console.log('Cover page, redirecting'); + // $(location).attr('href', 'Home.html'); + // } else { + // console.log('NOT COVER PAGE'); + // } + + console.log('before loadScript'); + const scriptURL = `bookshelf_${bookshelfURL}_${booksUrl}`; + // const scriptURL = "bookshelf_Adventure_lang_en_by_popularity.js" + console.log("loading bookshelf:", scriptURL); + loadScript(scriptURL, 'books_script', function() { + if ($('#books_table').attr('filled')) { + booksTable.fnDestroy(); + } + + $(document).ready(function() { + booksTable = $('#books_table').dataTable({ + initComplete: function(settings, json) { + var requestedPage = getPersistedPage(); + if (requestedPage) { + this.api() + .page(requestedPage) + .draw(false); + // fire event as not registered/ready yet + onTablePageChange(null, null, this); + } + }, + searching: false, + ordering: false, + deferRender: true, + bDeferRender: true, + lengthChange: false, + info: false, + data: json_data, + columns: [{ title: '' }, { title: '' }, { title: '' }], + bAutoWidth: false, + columnDefs: [ + { bVisible: false, aTargets: [1] }, + { sClass: 'table-icons', aTargets: [2] }, + { + targets: 0, + render: function(data, type, full, meta) { + div = '
'; + title = '' + full[3] + ''; + title += ' ' + full[0] + ''; + author = + full[1] == 'Anonymous' + ? '' + + document.webL10n.get('author-anonymous') + + '' + : full[1] == 'Various' + ? '' + + document.webL10n.get('author-various') + + '' + : '' + full[1] + ''; + + return div + '
' + title + '
' + author + ''; + } + if (data[1] == 1) { + html += + ''; + } + if (data[2] == 1) { + html += + ''; + } + + return html; + } + } + ] + }); + $('#books_table').on('page.dt', onTablePageChange); + }); + + /* Book list click handlers */ + $('#books_table').on('mouseup', 'tr td:first-child', function(event) { + var id = $('span', this)[0].innerHTML; + var titre = $('span.table-title', this)[0].innerHTML; + + if (event.which == 1) { + /* Left click */ + $(location).attr( + 'href', + encodeURIComponent(titre.replace('/', '-').substring(0, 230)) + + '_cover.' + + id + + '.html' + ); + } else if (event.which == 2) { + /* Middle click */ + var href = $(this).attr('data-href'); + var link = $( + '' + ); + link.attr('target', '_blank'); + window.open(link.attr('href')); + } + }); + + $('#books_table_paginate').click(function() { + minimizeUI(); + }); + $('#books_table').attr('filled', true); + + $('.sort').show(); + + /* Hide Spinner */ + inBooksLoadingLoop = false; + $('#spinner').hide(); + + /* Translate books table back/next buttons */ + $('#books_table_previous').attr('data-l10n-id', 'table-previous'); + $('#books_table_previous').html(document.webL10n.get('table-previous')); + $('#books_table_next').attr('data-l10n-id', 'table-next'); + $('#books_table_next').html(document.webL10n.get('table-next')); + }); + console.log('after loadScript'); + }); + console.log('after populateFilters'); +} function onLocalized() { var l10n = document.webL10n; var l10nselect = $('#l10nselect'); @@ -497,6 +669,7 @@ function init() { }, select: function(event, ui) { minimizeUI(); + $.persistValue('author_filter', ui.item.value, persist_options); showBooks(); } });