Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
1e6a756
Update deploy script to check git status
cclauss Sep 11, 2022
fdbc1b9
reword test titles
hornc Sep 13, 2022
c50e539
refactor down js ISBN checksum checks
hornc Sep 13, 2022
b2cb10c
Add pre-deploy.sh
cclauss Sep 15, 2022
2bee8c0
Add pre-deploy.sh
cclauss Sep 15, 2022
fed5b5d
Rename pre-deploy.sh to pre_deploy.sh
cclauss Sep 15, 2022
da855a8
Redirect to MR table on author MR submit
jimchamp Sep 15, 2022
71e9ef1
Redirect to MR table on work MR submission
jimchamp Sep 15, 2022
46c23bc
adding bulk redirect fix script
mekarpeles Sep 16, 2022
7cece8f
Update patron anonymization confirmation prompt
jimchamp Sep 16, 2022
a171e44
Require confirmation for blocking accounts
jimchamp Sep 16, 2022
1c09dd6
Bump `admin.*.js` bundlesize
jimchamp Sep 16, 2022
15faaf2
Update inside.html
mbrannon00 Sep 20, 2022
a5f227d
Update authors.html
mbrannon00 Sep 20, 2022
5d4742a
Remove `page` query param on show all requests
jimchamp Sep 20, 2022
848efb3
Filter merge requests by reviewed
jimchamp Sep 21, 2022
4569cf3
Update registration form copy
jimchamp Sep 21, 2022
2afe21c
Grant solr admin access to `librarians`
jimchamp Sep 22, 2022
be3866b
Refactor BarcodeScanner into class
cdrini Sep 21, 2022
9b7389b
Make "show_ol_shell" an ctx variable
cdrini Sep 22, 2022
b52ffd4
Add support for returnTo to OL barcodescanner
cdrini Sep 21, 2022
7feea06
Fix barcodescanner too big on mobile
cdrini Sep 22, 2022
fed5ebf
Add throttling to barcodescanner to reduce noise
cdrini Sep 22, 2022
03d3dd8
Fix barcodescanner not working on Android + Edge
cdrini Sep 22, 2022
4d13da5
fix text selection for selectable items
ztjhz Sep 23, 2022
873c6a1
[barcodescanner] Switch to Quagga2 + improve detection on iOS
cdrini Sep 23, 2022
2dc233b
Merge pull request #6476 from cdrini/feature/display-active-search-ed…
cdrini Sep 24, 2022
d5435ec
Use correct call to action for merge requesters
jimchamp Sep 24, 2022
3527469
Partial fix for #6755. Batch four of type hints from type comments. (…
scottbarnes Sep 24, 2022
b6ae6dc
fix trending pagination, coerce str to int (#6994)
mekarpeles Sep 25, 2022
edcd571
pre-commit autoupdate: pyupgrade v2.38.2 (#7000)
cclauss Sep 26, 2022
821d807
Block more words from auto-imports (#7001)
cdrini Sep 26, 2022
3831faf
Merge pull request #6999 from jimchamp/author-merge-ui-btn-copy
mekarpeles Sep 26, 2022
573b8a0
Merge pull request #6991 from jimchamp/librarian-permissions
mekarpeles Sep 26, 2022
60f2443
Merge pull request #6990 from jimchamp/registration-copy-update
mekarpeles Sep 26, 2022
09fbfb3
Subjects searchbttn (#6983)
mbrannon00 Sep 26, 2022
61b5e73
Work search header (#6984)
mbrannon00 Sep 26, 2022
1b66399
Merge pull request #6985 from mbrannon00/patch-1
mekarpeles Sep 26, 2022
c08f722
Merge pull request #6988 from cdrini/barcode-scanner-embed
mekarpeles Sep 27, 2022
cace863
Merge pull request #6982 from mbrannon00/inside_searchbttn
mekarpeles Sep 27, 2022
d5d1dca
Merge pull request #6971 from jimchamp/admin-people-improvements
mekarpeles Sep 27, 2022
61350eb
Merge pull request #6969 from jimchamp/inform-on-mr-submission
mekarpeles Sep 27, 2022
d6b8f32
Merge pull request #6956 from hornc/isbn_js
mekarpeles Sep 27, 2022
ee0fbb2
Merge pull request #6986 from jimchamp/feature/show-mr-reviewers
mekarpeles Sep 27, 2022
23deb8a
Merge pull request #6954 from internetarchive/add-git-status-to-are_s…
mekarpeles Sep 27, 2022
41feab4
Update dependency sinon to v13.0.2
renovate[bot] Sep 27, 2022
1c0c75a
Update dependency sinon to v14
renovate[bot] Sep 27, 2022
2d3585d
closes #7016 add indices to multi-pkey db schema (#7018)
mekarpeles Sep 27, 2022
3720269
removing profile and settings from My Books nav because they are in t…
szgrune Sep 27, 2022
c4d2a52
Merge pull request #7022 from szgrune/7020/fix/remove-profile-and-set…
mekarpeles Sep 27, 2022
19a3964
Merge pull request #6970 from internetarchive/resolve-redirects-bulk-…
cdrini Sep 28, 2022
28c557f
Create distinction between main nav links and hamburger links for ana…
jimchamp Sep 28, 2022
7401f9d
Merge pull request #6993 from ztjhz/6696/hotfix/text-selection-for-se…
cdrini Sep 28, 2022
426722c
Add timeout to DWWI request to fix sometimes being 50s (#7026)
cdrini Sep 28, 2022
43c8b03
Refactor worksearch.code works_by_author
cdrini Sep 21, 2022
d085820
Move location of worksearch sort preprocessing
cdrini Sep 21, 2022
3f2900d
Do not facet for Author.get_work_count
cdrini Sep 21, 2022
cc5e7b0
Rm unused methods Work.get_prev, get_next
cdrini Sep 21, 2022
ba85146
DRY worksearch.code top_books_from_author
cdrini Sep 21, 2022
4bd1d64
Delete duplicate work_search implementation for subjects
cdrini Sep 23, 2022
b45ebf6
Delete no longer used worksearch.subjects code
cdrini Sep 23, 2022
ddaf282
Tighten/fix issues in search.work_wrapper
cdrini Sep 23, 2022
7270294
Move worksearch.search.work_wrapper to .subjects
cdrini Sep 23, 2022
f593a62
Delete most of old /borrow, /read code
cdrini Sep 23, 2022
6eb7bb3
Fix run_solr_query does not throw errors
cdrini Sep 28, 2022
c427a72
Delete old custom urlencode
cdrini Sep 28, 2022
0b0aa61
Make Solr class use a single session for solr requests
cdrini Sep 28, 2022
ed59c2b
Use session for worksearch solr requests
cdrini Sep 29, 2022
a99656e
Fix commas causing user query failures
cdrini Sep 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ repos:
- types-all

- repo: https://github.com/asottile/pyupgrade
rev: v2.38.0
rev: v2.38.2
hooks:
- id: pyupgrade
args: # Solr on Cython is not yet ready for 3.10 type hints
Expand Down
2 changes: 1 addition & 1 deletion bundlesize.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
{
"path": "static/build/admin.*.js",
"maxSize": "1KB"
"maxSize": "1.3KB"
},
{
"path": "static/build/search.*.js",
Expand Down
7 changes: 7 additions & 0 deletions openlibrary/components/MergeUI.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ export default {
const splitKey = master.key.split('/')
const primaryRecord = splitKey[splitKey.length - 1]
await createMergeRequest(workIds, primaryRecord, 'create-pending', this.comment)
.then(response => response.json())
.then(data => {
if (data.status === 'ok') {
// Redirect to merge table on success:
window.location.replace(`/merges#mrid-${data.id}`)
}
})
}
this.mergeStatus = 'Done';
},
Expand Down
1 change: 1 addition & 0 deletions openlibrary/core/bookshelves.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def most_logged_books(
users. This query is limited to a specific shelf_id (e.g. 1
for "Want to Read").
"""
page = int(page or 1)
offset = (page - 1) * limit
oldb = db.get_db()
where = 'WHERE bookshelf_id' + ('=$shelf_id' if shelf_id else ' IS NOT NULL ')
Expand Down
2 changes: 1 addition & 1 deletion openlibrary/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ def resolve_redirects_bulk(
start_offset=0,
grace_period_days=7,
cutoff_date=datetime.datetime(year=2017, month=1, day=1),
test=True,
test=False,
):
"""
batch_size - how many records to fetch per batch
Expand Down
7 changes: 5 additions & 2 deletions openlibrary/core/schema.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@


CREATE TABLE ratings (
username text NOT NULL,
work_id integer NOT NULL,
Expand All @@ -9,6 +8,7 @@ CREATE TABLE ratings (
created timestamp without time zone default (current_timestamp at time zone 'utc'),
primary key (username, work_id)
);
CREATE INDEX ratings_work_id_idx ON ratings (work_id);

CREATE TABLE booknotes (
username text NOT NULL,
Expand All @@ -19,6 +19,7 @@ CREATE TABLE booknotes (
created timestamp without time zone default (current_timestamp at time zone 'utc'),
primary key (username, work_id, edition_id)
);
CREATE INDEX booknotes_work_id_idx ON booknotes (work_id);

CREATE TABLE bookshelves (
id serial not null primary key,
Expand All @@ -39,7 +40,8 @@ CREATE TABLE bookshelves_books (
created timestamp without time zone default (current_timestamp at time zone 'utc'),
primary key (username, work_id, bookshelf_id)
);

CREATE INDEX bookshelves_books_work_id_idx ON bookshelves_books (work_id);
-- bookshelves_votes currently unused
CREATE TABLE bookshelves_votes (
username text NOT NULL,
bookshelf_id serial NOT NULL REFERENCES bookshelves(id) ON DELETE CASCADE ON UPDATE CASCADE,
Expand All @@ -62,6 +64,7 @@ CREATE TABLE observations (
created timestamp without time zone default (current_timestamp at time zone 'utc'),
primary key (work_id, edition_id, username, observation_value, observation_type)
);
CREATE INDEX observations_username_idx ON observations (username);

CREATE TABLE community_edits_queue (
id serial not null primary key,
Expand Down
5 changes: 4 additions & 1 deletion openlibrary/core/sponsorships.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@ def do_we_want_it(isbn):
}
url = '%s/book/marc/ol_dedupe.php' % lending.config_ia_domain
try:
data = requests.get(url, params=params).json()
data = requests.get(url, params=params, timeout=2).json()
dwwi = data.get('response', 0)
return dwwi == 1, data.get('books', [])
except requests.exceptions.Timeout:
logger.exception('DWWI Timeout')
return False, []
except:
logger.error("DWWI Failed for isbn %s" % isbn, exc_info=True)
# err on the side of false negative
Expand Down
6 changes: 6 additions & 0 deletions openlibrary/plugins/admin/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ def handle(self, cls, args=(), librarians=False):
if not m:
raise web.nomethod(cls=cls)
else:
if (
context.user
and context.user.is_usergroup_member('/usergroup/librarians')
and web.ctx.path == '/admin/solr'
):
return m(*args)
if self.is_admin() or (
librarians
and context.user
Expand Down
205 changes: 11 additions & 194 deletions openlibrary/plugins/openlibrary/borrow_home.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
"""Controller for /borrow page.
"""
Controllers for /borrow pages.

These endpoints are largely deprecated, and only maintained for
backwards compatibility.
"""

import web
Expand All @@ -8,227 +12,40 @@

import eventer

from infogami.plugins.api.code import jsonapi
from infogami.utils import delegate
from infogami.utils.view import render_template # noqa: F401 used for its side effects

from openlibrary.core import helpers as h
from openlibrary.core import statsdb
from openlibrary.plugins.worksearch.subjects import SubjectEngine


class borrow(delegate.page): # TODO: Why is this function defined twice?
class borrow(delegate.page):
path = "/borrow"

def GET(self):
raise web.seeother('/subjects/in_library#ebooks=true')


class borrow(delegate.page): # type: ignore[no-redef]
class borrow_json(delegate.page):
path = "/borrow"
encoding = "json"

def is_enabled(self):
return "inlibrary" in web.ctx.features

@jsonapi
def GET(self):
i = web.input(
offset=0, limit=12, rand=-1, details="false", has_fulltext="false"
)

filters = {}
if i.get("has_fulltext") == "true":
filters["has_fulltext"] = "true"

if i.get("published_in"):
if "-" in i.published_in:
begin, end = i.published_in.split("-", 1)

if (
h.safeint(begin, None) is not None
and h.safeint(end, None) is not None
):
filters["publish_year"] = [begin, end]
else:
y = h.safeint(i.published_in, None)
if y is not None:
filters["publish_year"] = i.published_in
raise web.seeother('/subjects/in_library.json' + web.ctx.query)

i.limit = h.safeint(i.limit, 12)
i.offset = h.safeint(i.offset, 0)

i.rand = h.safeint(i.rand, -1)

if i.rand > 0:
sort = 'random_%d desc' % i.rand
filters['sort'] = sort

subject = get_lending_library(
web.ctx.site,
offset=i.offset,
limit=i.limit,
details=i.details.lower() == "true",
inlibrary=False,
**filters,
)
return json.dumps(subject)


class read(delegate.page): # TODO: Why is this function defined twice?
class read(delegate.page):
path = "/read"

def GET(self):
web.seeother('/subjects/accessible_book#ebooks=true')


class read(delegate.page): # type: ignore[no-redef]
class read_json(delegate.page):
path = "/read"
encoding = "json"

@jsonapi
def GET(self):
i = web.input(
offset=0, limit=12, rand=-1, details="false", has_fulltext="false"
)

filters = {}
if i.get("has_fulltext") == "true":
filters["has_fulltext"] = "true"

if i.get("published_in"):
if "-" in i.published_in:
begin, end = i.published_in.split("-", 1)

if (
h.safeint(begin, None) is not None
and h.safeint(end, None) is not None
):
filters["publish_year"] = [begin, end]
else:
y = h.safeint(i.published_in, None)
if y is not None:
filters["publish_year"] = i.published_in

i.limit = h.safeint(i.limit, 12)
i.offset = h.safeint(i.offset, 0)

i.rand = h.safeint(i.rand, -1)

if i.rand > 0:
sort = 'random_%d desc' % i.rand
filters['sort'] = sort

subject = get_readable_books(
web.ctx.site,
offset=i.offset,
limit=i.limit,
details=i.details.lower() == "true",
**filters,
)
return json.dumps(subject)


class borrow_about(delegate.page):
path = "/borrow/about"

def GET(self):
raise web.notfound()


def convert_works_to_editions(site, works):
"""Takes work docs got from solr and converts them into appropriate editions required for lending library."""
ekeys = [
'/books/' + w['lending_edition'] for w in works if w.get('lending_edition')
]
editions = {}
for e in site.get_many(ekeys):
editions[e['key']] = e.dict()

for w in works:
if w.get('lending_edition'):
ekey = '/books/' + w['lending_edition']
e = editions.get(ekey)
if e and 'ocaid' in e:
covers = e.get('covers') or [None]
w['key'] = e['key']
w['cover_id'] = covers[0]
w['ia'] = e['ocaid']
w['title'] = e.get('title') or w['title']


def get_lending_library(site, inlibrary=False, **kw):
kw.setdefault("sort", "first_publish_year desc")

if inlibrary:
subject = CustomSubjectEngine().get_subject(
"/subjects/lending_library", in_library=True, **kw
)
else:
subject = CustomSubjectEngine().get_subject(
"/subjects/lending_library", in_library=False, **kw
)

subject['key'] = '/borrow'
convert_works_to_editions(site, subject['works'])
return subject


def get_readable_books(site, **kw):
kw.setdefault("sort", "first_publish_year desc")
subject = ReadableBooksEngine().get_subject("/subjects/dummy", **kw)
subject['key'] = '/read'
return subject


class ReadableBooksEngine(SubjectEngine):
"""SubjectEngine for readable books.

This doesn't take subject into account, but considers the public_scan_b
field, which is derived from ia collections.

There is a subject "/subjects/accessible_book", but it has some
inlibrary/lendinglibrary books as well because of errors in OL data. Using
public_scan_b derived from ia collections is more accurate.
"""

def make_query(self, key, filters):
return {"public_scan_b": "true"}

def get_ebook_count(self, name, value, publish_year):
# we are not displaying ebook count.
# No point making a solr query
return 0


class CustomSubjectEngine(SubjectEngine):
"""SubjectEngine for inlibrary and lending_library combined."""

def make_query(self, key, filters):
meta = self.get_meta(key)

q = {
meta.facet_key: ["lending_library"],
'public_scan_b': "false",
'NOT borrowed_b': "true",
# show only books in last 20 or so years
'publish_year': (str(1990), str(datetime.date.today().year)), # range
}

if filters:
if filters.get('in_library') is True:
q[meta.facet_key].append('in_library')
if filters.get("has_fulltext") == "true":
q['has_fulltext'] = "true"
if filters.get("publish_year"):
q['publish_year'] = filters['publish_year']

return q

def get_ebook_count(self, name, value, publish_year):
# we are not displaying ebook count.
# No point making a solr query
return 0
web.seeother('/subjects/accessible_book.json' + web.ctx.query)


def on_loan_created_statsdb(loan):
Expand Down
19 changes: 18 additions & 1 deletion openlibrary/plugins/openlibrary/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,27 @@ export function initAdmin() {

export function initAnonymizationButton(button) {
const displayName = button.dataset.displayName;
const confirmMessage = `Really anonymize ${displayName}'s account? This will delete ${displayName}'s profile page and booknotes, and anonymize ${displayName}'s reading log, reviews, and star ratings.`;
const confirmMessage = `Really anonymize ${displayName}'s account? This will delete ${displayName}'s profile page and booknotes, and anonymize ${displayName}'s reading log, reviews, star ratings, and merge request submissions.`;
button.addEventListener('click', function(event) {
if (!confirm(confirmMessage)) {
event.preventDefault();
}
})
}

/**
* Adds click listener to each given button. When the button is clicked,
* the patron is prompted to confirm the action via a dialog.
*
* @param {NodeList<HTMLButtonElement>} buttons
*/
export function initConfirmationButtons(buttons) {
const confirmMessage = 'Are you sure?'
for (const button of buttons) {
button.addEventListener('click', function(event) {
if (!confirm(confirmMessage)) {
event.preventDefault();
}
})
}
}
Loading