Skip to content

Commit

Permalink
added project ui
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendan committed Sep 5, 2024
1 parent 7bcb682 commit 4fb1051
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 20 deletions.
Binary file added database.db
Binary file not shown.
3 changes: 2 additions & 1 deletion lilypad/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from contextlib import suppress

from . import app as app
from .prompts import prompt
from .tools import tools
from .trace import trace
Expand All @@ -10,4 +11,4 @@
from . import openai as openai


__all__ = ["openai", "prompt", "tools", "trace"]
__all__ = ["app", "openai", "prompt", "tools", "trace"]
Empty file added lilypad/app/__init__.py
Empty file.
Binary file added lilypad/app/database.db
Binary file not shown.
5 changes: 5 additions & 0 deletions lilypad/app/db/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""This module is responsible for handling the database connection."""

from .session import engine, get_session

__all__ = ["engine", "get_session"]
22 changes: 22 additions & 0 deletions lilypad/app/db/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Database session management"""

from collections.abc import Generator

from sqlmodel import Session, create_engine

from lilypad.app.models.projects import ProjectTable

engine = create_engine("sqlite:///database.db")


def get_session() -> Generator[Session, None, None]:
"""Get a SQLModel session"""
with Session(engine) as session:
yield session
try:
session.flush()
except Exception:
session.rollback()
raise
else:
session.commit()
8 changes: 8 additions & 0 deletions lilypad/app/db/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Create the database tables."""

from sqlmodel import SQLModel

from lilypad.app.db.session import engine
from lilypad.app.models import ProjectTable

SQLModel.metadata.create_all(engine)
57 changes: 48 additions & 9 deletions lilypad/app/main.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,61 @@
"""Main FastAPI application module for Lilypad."""

from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse
from typing import Annotated

from fastapi import Depends, FastAPI, Form, Query, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlmodel import Session, select

from lilypad.app.db.session import get_session
from lilypad.app.models.projects import ProjectTable

app = FastAPI()
templates = Jinja2Templates(directory="templates")


@app.get("/", response_class=HTMLResponse)
async def root(request: Request) -> HTMLResponse:
"""Render the index.html template."""
return templates.TemplateResponse("index.html", {"request": request})
async def projects(request: Request) -> HTMLResponse:
"""Render the projects.html template."""
return templates.TemplateResponse("projects.html", {"request": request})


@app.get("/projects", response_class=HTMLResponse)
async def get_projects(
request: Request,
session: Annotated[Session, Depends(get_session)],
) -> HTMLResponse:
"""Get all projects from the database."""
projects = session.exec(select(ProjectTable)).all()
return templates.TemplateResponse(
"partials/project_list.html", {"request": request, "projects": projects}
)


@app.post("/projects")
async def add_project(
request: Request,
session: Annotated[Session, Depends(get_session)],
project_name: str = Form(...),
) -> RedirectResponse:
"""Add a project to the database."""
project = ProjectTable(name=project_name)
session.add(project)
session.commit()
session.flush()
return RedirectResponse(url=f"/create-project/{project.name}", status_code=303)


@app.post("/submit", response_class=HTMLResponse)
async def submit(request: Request, input_value: str = Form(...)) -> HTMLResponse:
"""Render the result.html template."""
@app.get("/create-project/{project_name}", response_class=HTMLResponse)
async def create_project(
request: Request,
session: Annotated[Session, Depends(get_session)],
project_name: str,
) -> HTMLResponse:
"""Render the create_project.html template."""
project = session.exec(
select(ProjectTable).where(ProjectTable.name == project_name)
).first()
return templates.TemplateResponse(
"partials/result.html", {"request": request, "input_value": input_value}
"create_project.html", {"request": request, "project": project}
)
5 changes: 5 additions & 0 deletions lilypad/app/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""This module initializes the models package."""

from .projects import ProjectTable

__all__ = ["ProjectTable"]
20 changes: 20 additions & 0 deletions lilypad/app/models/projects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Project model"""

import datetime

from sqlmodel import Field

from lilypad.app.schemas.project import ProjectCreate

from .table_names import PROJECT_TABLE_TABLE


class ProjectTable(ProjectCreate, table=True):
"""Project model"""

__tablename__ = PROJECT_TABLE_TABLE # type: ignore

id: int | None = Field(default=None, primary_key=True)
created_at: datetime.datetime = Field(
default=datetime.datetime.now(datetime.UTC), nullable=False
)
3 changes: 3 additions & 0 deletions lilypad/app/models/table_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Table names for the database models."""

PROJECT_TABLE_TABLE = "projects"
5 changes: 5 additions & 0 deletions lilypad/app/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""This module is responsible for handling the database schemas."""

from .base_sql_model import BaseSQLModel

__all__ = ["BaseSQLModel"]
21 changes: 21 additions & 0 deletions lilypad/app/schemas/base_sql_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pydantic import ConfigDict
from sqlmodel import SQLModel


class BaseSQLModel(SQLModel):
"""Base SQLModel class"""

model_config = ConfigDict( # pyright:ignore[reportAssignmentType]
populate_by_name=True,
from_attributes=True,
validate_assignment=True,
)


BaseSQLModel.metadata.naming_convention = {
"ix": "%(column_0_label)s_idx",
"uq": "%(table_name)s_%(column_0_name)s_key",
"ck": "%(table_name)s_%(constraint_name)s_check",
"fk": "%(table_name)s_%(column_0_name)s_%(referred_table_name)s_fkey",
"pk": "%(table_name)s_pkey",
}
11 changes: 11 additions & 0 deletions lilypad/app/schemas/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Project schema"""

from sqlmodel import Field

from .base_sql_model import BaseSQLModel


class ProjectCreate(BaseSQLModel):
"""project schema"""

name: str = Field(nullable=False, unique=True)
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTMX 2.0 Input Example</title>
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
<title>HTMX Form</title>
<script src="https://unpkg.com/htmx.org@2.0.0/dist/htmx.min.js"></script>
</head>
<body>
<h1>HTMX 2.0 Input Example</h1>
<h1>{{ project.name }}</h1>
<form hx-post="/submit" hx-target="#result">
<input type="text" name="input_value" placeholder="Type something..." />
<textarea name="content" rows="4" cols="50"></textarea>
<br />
<button type="submit">Submit</button>
</form>
<button hx-get="/" hx-target="body" hx-push-url="true">Back</button>
<div id="result"></div>
</body>
</html>
7 changes: 7 additions & 0 deletions lilypad/app/templates/partials/project_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% for project in projects %}
<li>
<a href="create-project/{{project.name}}" hx-push-url="true"
>{{ project.name }}</a
>
</li>
{% endfor %}
1 change: 0 additions & 1 deletion lilypad/app/templates/partials/result.html

This file was deleted.

22 changes: 22 additions & 0 deletions lilypad/app/templates/projects.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Project List</title>
<script src="https://unpkg.com/htmx.org@2.0.0/dist/htmx.min.js"></script>
</head>
<body>
<h1>Project List</h1>

<form hx-post="/projects" hx-target="body" hx-push-url="true">
<input type="text" name="project_name" placeholder="Enter a project..." />
<button type="submit">Add Project</button>
</form>

<div id="projects">
<h2>Projects:</h2>
<ul id="project-list" hx-get="/projects" hx-trigger="load"></ul>
</div>
</body>
</html>
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ classifiers = [
]
dependencies = [
"mirascope>=1.1.2",
"fastapi[standard]>=0.112.2",
"fastapi[standard]>=0.113",
"sqlmodel>=0.0.22",
"psycopg2-binary>=2.9.9",
]

[project.urls]
Expand Down
Loading

0 comments on commit 4fb1051

Please sign in to comment.