Skip to content

Commit

Permalink
study and error handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
ZanSara committed Aug 5, 2023
1 parent 41fc2b5 commit c9ee039
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 42 deletions.
10 changes: 0 additions & 10 deletions .pre-commit-config.yaml

This file was deleted.

36 changes: 29 additions & 7 deletions flashcards_htmx/api/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from jinja2 import Template
import starlette.status as status
from fastapi import APIRouter, Request, Depends
from fastapi import APIRouter, Request, Depends, HTTPException
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates

Expand Down Expand Up @@ -37,6 +37,9 @@ async def cards_component(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

card_templates = db["templates"]
for card in deck["cards"].values():
card["preview"] = Template(card_templates[card["type"]]["preview"]).render(**card["data"])
Expand All @@ -49,14 +52,24 @@ async def study_component(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not len(deck["cards"]):
return render(card=None)
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

if not len(deck["cards"]):
return render(card=None, deck_id=deck_id)

# TODO actually get the card to study from the deck
card_id = randint(1, len(deck["cards"]))
# if card_id == "1":
# return render(error="Test Error")

# if card_id == "1":
# return render(error="Test Error")
card = deck["cards"].get(str(card_id), {})
if not card:
raise HTTPException(status_code=404, detail="Card not found")

card["rendered_question"] = Template(db["templates"][card["type"]]["question"]).render(**card["data"]["question"])
card["rendered_answer"] = Template(db["templates"][card["type"]]["answer"]).render(**card["data"]["answer"])

# TODO actually get the card to study from the deck
card_id = randint(0, len(deck["cards"]))
return render(deck=deck, deck_id=deck_id, card=deck["cards"][str(card_id)], card_id=str(card_id))


Expand All @@ -68,6 +81,9 @@ async def save_review_component(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

deck["cards"][card_id]["reviews"][len(deck["cards"][card_id]["reviews"])] = {
"date": datetime.datetime.utcnow().isoformat(),
"result": result,
Expand All @@ -84,6 +100,9 @@ async def deck_confirm_delete_component(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

return render(
title=f"Deleting {deck['name']}",
content=f"Are you really sure you wanna delete the deck {deck['name']}? It contains {len(deck['cards'])} cards.",
Expand All @@ -102,6 +121,9 @@ async def card_confirm_delete_component(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

return render(
title=f"Deleting card n. {deck['cards'][card_id]['id']}",
content=f"Are you really sure you wanna delete this card? [TODO show card preview]",
Expand Down
21 changes: 21 additions & 0 deletions flashcards_htmx/api/json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import shelve
import starlette.status as status
from fastapi import APIRouter, Request, Depends
from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse, JSONResponse

from flashcards_htmx.app import template, database


router = APIRouter()


@router.get("/export/{deck_id}", response_class=FileResponse)
async def export_deck_endpoint(request: Request):
with shelve.open(database) as db:
deck = db["decks"].get(request.path_params["deck_id"], {})
if not deck:
return JSONResponse(status_code=404, content={"message": "Item not found"})
path = f"tmp/{deck}.json"

return FileResponse(path)

26 changes: 21 additions & 5 deletions flashcards_htmx/api/private.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from jinja2 import Template
import starlette.status as status
from fastapi import APIRouter, Request, Depends
from fastapi import APIRouter, Request, Depends, HTTPException
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates

Expand Down Expand Up @@ -35,6 +35,8 @@ async def profile_page(render=Depends(template("private/profile.html"))):
async def study_page(deck_id: str, render=Depends(template("private/study.html"))):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
return render(navbar_title=deck["name"], deck=deck, deck_id=deck_id)


Expand All @@ -53,6 +55,8 @@ async def create_deck_page(render=Depends(template("private/deck.html"))):
async def edit_deck_page(deck_id: str, render=Depends(template("private/deck.html"))):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
return render(navbar_title=deck["name"], deck=deck, deck_id=deck_id)


Expand All @@ -79,6 +83,8 @@ async def cards_page(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
return render(
navbar_title=deck["name"],
deck=deck,
Expand All @@ -93,6 +99,9 @@ async def cards_page(
async def create_card_page(deck_id: str, render=Depends(template("private/card.html"))):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

id = len(db["decks"].get(deck_id, {}).get("cards", {})) + 1
card_templates = db["templates"]
for template in card_templates.values():
Expand All @@ -110,6 +119,7 @@ async def create_card_page(deck_id: str, render=Depends(template("private/card.h
},
"tags": [],
"type": "Q/A",
"reviews": {},
},
card_id=id,
card_templates=card_templates
Expand All @@ -122,8 +132,14 @@ async def edit_card_page(
):
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")

card_templates = db["templates"]
card = deck["cards"][card_id]
card = deck["cards"].get(card_id, {})
if not card:
raise HTTPException(status_code=404, detail="Card not found")

for template in card_templates.values():
template["rendered_form"] = Template(template["form"]).render(**card["data"])

Expand All @@ -142,7 +158,8 @@ async def save_card_endpoint(deck_id: str, card_id: Optional[str], request: Requ
async with request.form() as form:
with shelve.open(database) as db:
deck = db["decks"].get(deck_id, {})
card = {
deck["cards"][card_id] = {
**deck["cards"].get(card_id, {"reviews": {}}),
"data": {
"question": {
key[len("question."):] : value for key, value in form.items() if key.startswith("question.")
Expand All @@ -157,10 +174,9 @@ async def save_card_endpoint(deck_id: str, card_id: Optional[str], request: Requ
"tags": [tag.strip() for tag in form["tags"].split(",") if tag.strip()],
"type": form["type"],
}
deck["cards"][card_id] = card

return RedirectResponse(
request.url_for("home_page"), status_code=status.HTTP_302_FOUND
request.url_for("cards_page", deck_id=deck_id), status_code=status.HTTP_302_FOUND
)


Expand Down
34 changes: 23 additions & 11 deletions flashcards_htmx/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from fastapi import Request, Depends
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from fastapi.exceptions import HTTPException, StarletteHTTPException


__version__ = importlib.metadata.version("flashcards_htmx")
Expand Down Expand Up @@ -64,6 +66,7 @@
}
"""


database = "flashcards.db"
shelve.open = partial(shelve.open, writeback=True)

Expand All @@ -85,17 +88,6 @@
})


# Create the FastAPI app
app = FastAPI(
title="Flashcards HTMX webserver",
description="API Docs for flashcards-htmx",
version=__version__,
)
app.mount(
"/static", StaticFiles(directory=Path(__file__).parent / "static"), name="static"
)


def get_jinja2():
"""Get Jinja2 dependency function. you can define more functions, filters or global vars here"""

Expand Down Expand Up @@ -125,12 +117,32 @@ def render(*args, **kwargs):
return func_view


# Create the FastAPI app
app = FastAPI(
title="Flashcards HTMX webserver",
description="API Docs for flashcards-htmx",
version=__version__,
)
app.mount(
"/static", StaticFiles(directory=Path(__file__).parent / "static"), name="static"
)


@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
template = get_jinja2().get_template("public/http_error.html")
response = template.render(request=request, code=exc.status_code, message=exc.detail)
return HTMLResponse(response)


from flashcards_htmx.api.public import router as public_router # noqa: F401, E402
from flashcards_htmx.api.private import router as private_router # noqa: F401, E402
from flashcards_htmx.api.components import (
router as private_components,
) # noqa: F401, E402
from flashcards_htmx.api.json import router as json_router # noqa: F401, E402

app.include_router(public_router)
app.include_router(private_router)
app.include_router(private_components)
app.include_router(json_router)
2 changes: 1 addition & 1 deletion flashcards_htmx/static/css/private-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ section.cards {
.tags {
display: flex;
justify-items: center;
gap: 0.5rem;
gap: 0;
margin: 0 1rem;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

<main class="wrapper">

<h1>Not Found - 404</h1>
<p>We could not find what you're looking for :(</p>
<h1>{{ code }}</h1>
<p>{{ message }}</p>

<footer>
<a href="{{ url_for('home_page') }}">Go back</a>
Expand Down
10 changes: 4 additions & 6 deletions flashcards_htmx/templates/responses/study.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,21 @@ <h1>No Cards!</h1>
check your deck settings and make sure your deck contains cards.
</p>
<div class="buttons">
<a href="{{ url_for('home_page') }}">Go Back</a>
<a href="{{ url_for('cards_page', deck_id=deck_id) }}">Add cards</a>
</div>
</div>

{% else %}

<h1 id="question">{{ card.question }}</h1>
<h1 id="question">{{ card.rendered_question }}</h1>

<input id="guess" type="text" placeholder="Your Answer..."></input>

<details id="collapsible">
<summary>
<summary autofocus>
<a>Show the answer</a>
</summary>

<div class="feedback">
<h1 id="answer">{{ card.answer }}</h1>
<h1 id="answer">{{ card.rendered_answer }}</h1>

<div class="buttons">
<button type="button" class="positive"
Expand Down

0 comments on commit c9ee039

Please sign in to comment.