mirror of
https://github.com/th3r00t/pyShelf.git
synced 2026-04-28 01:59:35 -04:00
Fixed mobile menu
This commit is contained in:
19
src/backend/lib/models.py
vendored
19
src/backend/lib/models.py
vendored
@@ -68,3 +68,22 @@ class BookCollection(Base):
|
||||
# Relationships
|
||||
book = relationship("Book", back_populates="book_collections")
|
||||
collection = relationship("Collection", back_populates="book_collections")
|
||||
|
||||
class User(Base):
|
||||
"""User model."""
|
||||
|
||||
__tablename__ = "User"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, nullable=False)
|
||||
username: Mapped[str] = mapped_column(unique=True, nullable=False)
|
||||
password: Mapped[str] = mapped_column(nullable=False)
|
||||
email: Mapped[Optional[str]] = mapped_column(unique=True, nullable=True)
|
||||
date_joined: Mapped[timestamp] = mapped_column(
|
||||
nullable=False, server_default=func.CURRENT_TIMESTAMP()
|
||||
)
|
||||
last_login: Mapped[Optional[timestamp]] = mapped_column(
|
||||
nullable=True, server_default=None
|
||||
)
|
||||
is_active: Mapped[bool] = mapped_column(nullable=False, default=True)
|
||||
is_admin: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||
is_superuser: Mapped[bool] = mapped_column(nullable=False, default=False)
|
||||
|
||||
17
src/backend/lib/storage.py
vendored
17
src/backend/lib/storage.py
vendored
@@ -271,23 +271,6 @@ class Storage:
|
||||
session.close()
|
||||
return _result
|
||||
|
||||
# def fuzzy_search_books(self, query: str, limit: int = 30):
|
||||
# """Fuzzy search for books by title, author, or tags."""
|
||||
# with Session(self.engine) as session:
|
||||
# books = session.execute(select(Book)).scalars().all()
|
||||
#
|
||||
# # Prepare a combined text field
|
||||
# book_choices = {book.id: f"{book.title or ''} {book.author or ''} {book.tags or ''}"
|
||||
# for book in books}
|
||||
#
|
||||
# # Use RapidFuzz to score
|
||||
# results = process.extract(query, book_choices, scorer=fuzz.WRatio, limit=limit)
|
||||
#
|
||||
# # results = [(matched_text, score, book_id), ...]
|
||||
# book_ids = [book_id for (_, score, book_id) in results if score > 50] # threshold
|
||||
# books = [b for b in books if b.id in book_ids]
|
||||
# return books
|
||||
|
||||
|
||||
def parse_advanced_query(self, query: str) -> dict:
|
||||
"""Parse a query like 'title:"dark tower" author:king tags:fantasy'"""
|
||||
|
||||
@@ -15,7 +15,7 @@ const collections = {{ collections|collections_tojson }};
|
||||
<div id="navbarMain" class="navbar-menu">
|
||||
<div class="navbar-start is-flex is-flex-grow-1">
|
||||
<a class="navbar-item" href="/">Home</a>
|
||||
<div class="navbar-item is-flex-grow-1 px-2">
|
||||
<div class="is-hidden-touch navbar-item is-flex-grow-1 px-2">
|
||||
<div class="field is-grouped is-fullwidth" style="width: 100%;">
|
||||
<p class="control is-expanded">
|
||||
<span class="select is-small is-rounded is-link is-fullwidth">
|
||||
@@ -26,7 +26,6 @@ const collections = {{ collections|collections_tojson }};
|
||||
{% endif %}
|
||||
{% for collection in collections %}
|
||||
<option value="{{collection.id}}" class="collection_selection">
|
||||
<!-- {{collection.name[:80]}} -->
|
||||
{{collection.name}}
|
||||
</option>
|
||||
{% endfor %}
|
||||
@@ -35,7 +34,7 @@ const collections = {{ collections|collections_tojson }};
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item is-flex-grow-1 px-2">
|
||||
<div class="is-hidden-touch navbar-item is-flex-grow-1 px-2">
|
||||
<form action="/api/search" method="get" class="field has-addons is-flex-grow-1">
|
||||
<div class="control is-expanded">
|
||||
<input
|
||||
@@ -90,5 +89,55 @@ const collections = {{ collections|collections_tojson }};
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mobile-only -->
|
||||
<div class="navbar-item is-hidden-desktop">
|
||||
<div class="field is-grouped is-fullwidth">
|
||||
<p class="control is-expanded">
|
||||
<span class="select is-small is-rounded is-link is-fullwidth">
|
||||
<select id="collection_select_mobile">
|
||||
<option value="" disabled selected>Select a collection</option>
|
||||
{% if collections is not defined or collections|length == 0 %}
|
||||
<option value="" disabled>No collections available</option>
|
||||
{% endif %}
|
||||
{% for collection in collections %}
|
||||
<option value="{{collection.id}}" class="collection_selection">
|
||||
{{collection.name}}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<form action="/api/search" method="get" class="field has-addons is-fullwidth mt-2">
|
||||
<div class="control is-expanded">
|
||||
<input
|
||||
class="input is-small is-dark is-link is-rounded-left"
|
||||
type="text"
|
||||
name="search"
|
||||
placeholder="Search books..." />
|
||||
</div>
|
||||
<div class="control">
|
||||
<button
|
||||
class="button is-small is-dark is-link is-rounded-right"
|
||||
type="submit">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
<script>
|
||||
document.getElementById("collection_select")?.addEventListener("change", function () {
|
||||
const value = encodeURIComponent(this.value);
|
||||
window.location.href = `/api/collection/${value}`;
|
||||
});
|
||||
|
||||
document.getElementById("collection_select_mobile")?.addEventListener("change", function () {
|
||||
const value = encodeURIComponent(this.value);
|
||||
window.location.href = `/api/collection/${value}`;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user