def has_book_note(self, username, edition_olid): if not username: return False work_id = extract_numeric_id_from_olid(self.key) edition_id = extract_numeric_id_from_olid(edition_olid) return (len( Booknotes.get_patron_booknote( username, work_id, edition_id=edition_id)) > 0)
def get_users_notes(self, username, edition_olid=None): if not username: return None work_id = extract_numeric_id_from_olid(self.key) edition_id = extract_numeric_id_from_olid( edition_olid) if edition_olid else -1 return Booknotes.get_patron_booknote(username, work_id, edition_id=edition_id)
def get_users_read_status(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) status_id = Bookshelves.get_users_read_status_of_work( username, work_id) return status_id
def get_rating_stats(self): work_id = extract_numeric_id_from_olid(self.key) rating_stats = Ratings.get_rating_stats(work_id) if rating_stats and rating_stats['num_ratings'] > 0: return { 'avg_rating': round(rating_stats['avg_rating'], 2), 'num_ratings': rating_stats['num_ratings'] }
def get_num_users_by_bookshelf(self): work_id = extract_numeric_id_from_olid(self.key) num_users_by_bookshelf = Bookshelves.get_num_users_by_bookshelf_by_work_id(work_id) return { 'want-to-read': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Want to Read'], 0), 'currently-reading': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Currently Reading'], 0), 'already-read': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Already Read'], 0) }
def get_rating_stats(self): work_id = extract_numeric_id_from_olid(self.key) rating_stats = Ratings.get_rating_stats(work_id) if rating_stats and rating_stats['num_ratings'] > 0: return { 'avg_rating': round(rating_stats['avg_rating'],2), 'num_ratings': rating_stats['num_ratings'] }
def get_num_users_by_bookshelf(self): work_id = extract_numeric_id_from_olid(self.key) num_users_by_bookshelf = Bookshelves.get_num_users_by_bookshelf_by_work_id(work_id) return { 'want-to-read': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Want to Read'], 0), 'currently-reading': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Currently Reading'], 0), 'already-read': num_users_by_bookshelf.get(Bookshelves.PRESET_BOOKSHELVES['Already Read'], 0) }
def get_users_observations(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) raw_observations = Observations.get_patron_observations(username, work_id) formatted_observations = defaultdict(list) for r in raw_observations: kv_pair = Observations.get_key_value_pair(r['type'], r['value']) formatted_observations[kv_pair.key].append(kv_pair.value) return formatted_observations
def add_read_statuses(username, works): work_ids = [ extract_numeric_id_from_olid(work.key.split('/')[-1]) for work in works ] results = Bookshelves.get_users_read_status_of_works(username, work_ids) results_map = {} for result in results: results_map[f"OL{result['work_id']}W"] = result['bookshelf_id'] for work in works: work_olid = work.key.split('/')[-1] work['readinglog'] = results_map.get(work_olid, None) return works
def POST(self, work_id): """Registers new ratings for this work""" user = accounts.get_current_user() i = web.input( edition_id=None, rating=None, redir=False, redir_url=None, page=None, ajax=False, ) key = (i.redir_url if i.redir_url else i.edition_id if i.edition_id else ('/works/OL%sW' % work_id)) edition_id = (int(extract_numeric_id_from_olid(i.edition_id)) if i.edition_id else None) if not user: raise web.seeother('/account/login?redirect=%s' % key) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(json.dumps({status: msg}), content_type="application/json") if i.rating is None: models.Ratings.remove(username, work_id) r = response('removed rating') else: try: rating = int(i.rating) if rating not in models.Ratings.VALID_STAR_RATINGS: raise ValueError except ValueError: return response('invalid rating', status="error") models.Ratings.add(username=username, work_id=work_id, rating=rating, edition_id=edition_id) r = response('rating added') if i.redir and not i.ajax: p = h.safeint(i.page, 1) query_params = f'?page={p}' if p > 1 else '' if i.page: raise web.seeother(f'{key}{query_params}') raise web.seeother(key) return r
def POST(self, work_id): """ Add a note to a work (or a work and an edition) GET params: - edition_id str (optional) - redir bool: if patron not logged in, redirect back to page after login :param str work_id: e.g. OL123W :rtype: json :return: the note """ user = accounts.get_current_user() i = web.input(notes=None, edition_id=None, redir=None) edition_id = int( extract_numeric_id_from_olid(i.edition_id)) if i.edition_id else -1 if not user: raise web.seeother('/account/login?redirect=/works/%s' % work_id) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(json.dumps({ status: msg }), content_type="application/json") if i.notes is None: Booknotes.remove(username, work_id, edition_id=edition_id) return response('removed note') Booknotes.add( username=username, work_id=work_id, notes=i.notes, edition_id=edition_id ) if i.redir: raise web.seeother("/works/%s" % work_id) return response('note added')
def POST(self, work_id): """Registers new ratings for this work""" user = accounts.get_current_user() i = web.input(edition_id=None, rating=None, redir=False) key = i.edition_id if i.edition_id else ('/works/OL%sW' % work_id) edition_id = int(extract_numeric_id_from_olid( i.edition_id)) if i.edition_id else None if not user: raise web.seeother('/account/login?redirect=%s' % key) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(simplejson.dumps({status: msg}), content_type="application/json") if i.rating is None: models.Ratings.remove(username, work_id) r = response('removed rating') else: try: rating = int(i.rating) if rating not in models.Ratings.VALID_STAR_RATINGS: raise ValueError except ValueError: return response('invalid rating', status="error") models.Ratings.add(username=username, work_id=work_id, rating=rating, edition_id=edition_id) r = response('rating added') if i.redir: raise web.seeother(key) return r
def POST(self, work_id): """Registers new ratings for this work""" user = accounts.get_current_user() i = web.input(edition_id=None, rating=None, redir=False) key = i.edition_id if i.edition_id else ('/works/OL%sW' % work_id) edition_id = int(extract_numeric_id_from_olid(i.edition_id)) if i.edition_id else None if not user: raise web.seeother('/account/login?redirect=%s' % key) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(simplejson.dumps({ status: msg }), content_type="application/json") if i.rating is None: models.Ratings.remove(username, work_id) r = response('removed rating') else: try: rating = int(i.rating) if rating not in models.Ratings.VALID_STAR_RATINGS: raise ValueError except ValueError: return response('invalid rating', status="error") models.Ratings.add( username=username, work_id=work_id, rating=rating, edition_id=edition_id) r = response('rating added') if i.redir: raise web.seeother(key) return r
def get_users_notes(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) return Booknotes.get_patron_booknote(username, work_id)
def get_users_read_status(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) status_id = Bookshelves.get_users_read_status_of_work(username, work_id) return status_id
def get_users_rating(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) rating = Ratings.get_users_rating_for_work(username, work_id) return rating
def get_users_rating(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) rating = Ratings.get_users_rating_for_work(username, work_id) return rating
def test_extract_numeric_id_from_olid(): assert extract_numeric_id_from_olid('/works/OL123W') == '123' assert extract_numeric_id_from_olid('OL123W') == '123'
def get_observation_metrics(work_olid): """ Returns a dictionary of observation statistics for the given work. Statistics will be used to populate a book's "Reader Observations" component. Dictionary will have the following structure: { 'work_id': 12345, 'total_respondents': 100, 'observations': [ { 'label': 'pace', 'description': 'What is the pace of this book?', 'multi_choice': False, 'total_respondents_for_type': 10, 'values': [ { 'value': 'fast', 'count': 6 }, { 'value': 'medium', 'count': 4 } ] } ... Other observations omitted for brevity ... ] } If no observations were made for a specific type, that type will be excluded from the 'observations' list. Items in the 'observations.values' list will be ordered from greatest count to least. return: A dictionary of observation statistics for a work. """ work_id = extract_numeric_id_from_olid(work_olid) total_respondents = Observations.total_unique_respondents(work_id) metrics = {} metrics['work_id'] = work_id metrics['total_respondents'] = total_respondents metrics['observations'] = [] if total_respondents > 0: respondents_per_type_dict = Observations.count_unique_respondents_by_type( work_id) observation_totals = Observations.count_observations(work_id) current_type_id = observation_totals[0]['type_id'] observation_item = next((o for o in OBSERVATIONS['observations'] if current_type_id == o['id'])) current_observation = { 'label': observation_item['label'], 'description': observation_item['description'], 'multi_choice': observation_item['multi_choice'], 'total_respondents_for_type': respondents_per_type_dict[current_type_id], 'values': [] } for i in observation_totals: if i['type_id'] != current_type_id: metrics['observations'].append(current_observation) current_type_id = i['type_id'] observation_item = next((o for o in OBSERVATIONS['observations'] if current_type_id == o['id'])) current_observation = { 'label': observation_item['label'], 'description': observation_item['description'], 'multi_choice': observation_item['multi_choice'], 'total_respondents_for_type': respondents_per_type_dict[current_type_id], 'values': [] } current_observation['values'].append({ 'value': next((v['name'] for v in observation_item['values'] if v['id'] == i['value_id'])), 'count': i['total'] }) metrics['observations'].append(current_observation) return metrics
def test_extract_numeric_id_from_olid(): assert extract_numeric_id_from_olid('/works/OL123W') == '123' assert extract_numeric_id_from_olid('OL123W') == '123'
def get_read_status(work_key, username): work_id = extract_numeric_id_from_olid(work_key.split('/')[-1]) return Bookshelves.get_users_read_status_of_work(username, work_id)