Enable htmx
This commit is contained in:
@@ -6,7 +6,7 @@ Provides clean URL structure and integrates with library.py business logic.
|
|||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Annotated, Any
|
from typing import Annotated, Any, Literal
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Blueprint,
|
Blueprint,
|
||||||
@@ -39,7 +39,7 @@ bp = Blueprint("main", __name__)
|
|||||||
# Pydantic validation models
|
# Pydantic validation models
|
||||||
StrOrNone = Annotated[str | None, BeforeValidator(lambda v: v.strip() or None)]
|
StrOrNone = Annotated[str | None, BeforeValidator(lambda v: v.strip() or None)]
|
||||||
StripStr = Annotated[str, StringConstraints(strip_whitespace=True)]
|
StripStr = Annotated[str, StringConstraints(strip_whitespace=True)]
|
||||||
ISBNOrNone = Annotated[ISBN | None, BeforeValidator(lambda v: v.strip() or None)]
|
ISBNOrEmpty = Annotated[ISBN | Literal[""], BeforeValidator(lambda v: v.strip() or "")]
|
||||||
TextareaList = Annotated[
|
TextareaList = Annotated[
|
||||||
list[str],
|
list[str],
|
||||||
BeforeValidator(
|
BeforeValidator(
|
||||||
@@ -57,7 +57,7 @@ IntOrNone = Annotated[int | None, BeforeValidator(lambda v: v.strip() or None)]
|
|||||||
class BookFormData(BaseModel):
|
class BookFormData(BaseModel):
|
||||||
title: StripStr = Field(min_length=1)
|
title: StripStr = Field(min_length=1)
|
||||||
owner: StrOrNone = None
|
owner: StrOrNone = None
|
||||||
isbn: ISBNOrNone = None
|
isbn: ISBNOrEmpty = ""
|
||||||
authors: TextareaList = Field(default_factory=list)
|
authors: TextareaList = Field(default_factory=list)
|
||||||
genres: TextareaList = Field(default_factory=list)
|
genres: TextareaList = Field(default_factory=list)
|
||||||
first_published: IntOrNone = Field(default=None, le=2030)
|
first_published: IntOrNone = Field(default=None, le=2030)
|
||||||
@@ -205,7 +205,7 @@ def create_book() -> ResponseReturnValue:
|
|||||||
owner_id=owner_id,
|
owner_id=owner_id,
|
||||||
authors=form_data.authors,
|
authors=form_data.authors,
|
||||||
genres=form_data.genres,
|
genres=form_data.genres,
|
||||||
isbn=str(form_data.isbn) if form_data.isbn else None,
|
isbn=str(form_data.isbn),
|
||||||
publisher=form_data.publisher,
|
publisher=form_data.publisher,
|
||||||
edition=form_data.edition,
|
edition=form_data.edition,
|
||||||
description=form_data.description,
|
description=form_data.description,
|
||||||
@@ -256,7 +256,7 @@ def update_book(book_id: int) -> ResponseReturnValue:
|
|||||||
owner_id=owner_id,
|
owner_id=owner_id,
|
||||||
authors=form_data.authors,
|
authors=form_data.authors,
|
||||||
genres=form_data.genres,
|
genres=form_data.genres,
|
||||||
isbn=str(form_data.isbn) if form_data.isbn else None,
|
isbn=form_data.isbn,
|
||||||
publisher=form_data.publisher,
|
publisher=form_data.publisher,
|
||||||
edition=form_data.edition,
|
edition=form_data.edition,
|
||||||
description=form_data.description,
|
description=form_data.description,
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16x16.png') }}">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16x16.png') }}">
|
||||||
<link rel="manifest" href="{{ url_for('static', filename='site.webmanifest') }}">
|
<link rel="manifest" href="{{ url_for('static', filename='site.webmanifest') }}">
|
||||||
|
|
||||||
{#
|
|
||||||
<script src="{{ url_for('static', filename='htmx.min.js') }}"></script> #}
|
<script src="{{ url_for('static', filename='htmx.min.js') }}"></script>
|
||||||
{#
|
{#
|
||||||
<script src="{{ url_for('static', filename='alpine.min.js') }}" defer></script> #}
|
<script src="{{ url_for('static', filename='alpine.min.js') }}" defer></script> #}
|
||||||
{#
|
{#
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body hx-boost="true">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
{% include 'components/header.html.j2' %}
|
{% include 'components/header.html.j2' %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="card book-card h-100" onclick="window.location.href='/book/{{ book.id }}'">
|
<a href="/book/{{ book.id }}" class="card book-card h-100 text-decoration-none text-reset">
|
||||||
<div class="position-relative">
|
<div class="position-relative">
|
||||||
<!-- TODO: Book cover image -->
|
<!-- TODO: Book cover image -->
|
||||||
<div class="card-img-top bg-light d-flex align-items-center justify-content-center text-muted">
|
<div class="card-img-top bg-light d-flex align-items-center justify-content-center text-muted">
|
||||||
@@ -73,4 +73,4 @@
|
|||||||
<small class="text-muted"> • {{ book.location_place }}</small>
|
<small class="text-muted"> • {{ book.location_place }}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
Reference in New Issue
Block a user