-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from Mirascope/add-project-ui
added project ui
- Loading branch information
Showing
21 changed files
with
497 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""The lilypad app module.""" |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"""Database session management""" | ||
|
||
from collections.abc import Generator | ||
|
||
from sqlmodel import Session, create_engine | ||
|
||
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 * # noqa: F403 | ||
|
||
SQLModel.metadata.create_all(engine) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,159 @@ | ||
"""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, HTTPException, 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 import ProjectTable, PromptVersionTable | ||
|
||
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"/projects/{project.name}", status_code=303) | ||
|
||
|
||
@app.get("/projects/{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( | ||
"create_project.html", {"request": request, "project": project} | ||
) | ||
|
||
|
||
@app.get("/projects/{project_name}", response_class=HTMLResponse) | ||
async def show_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( | ||
"create_project.html", {"request": request, "project": project} | ||
) | ||
|
||
|
||
@app.get("/projects/{project_name}/versions", response_class=HTMLResponse) | ||
async def get_prompt_versions( | ||
request: Request, | ||
session: Annotated[Session, Depends(get_session)], | ||
project_name: str, | ||
) -> HTMLResponse: | ||
"""Render the version_list.html template.""" | ||
project = session.exec( | ||
select(ProjectTable).where(ProjectTable.name == project_name) | ||
).first() | ||
|
||
if not project: | ||
raise HTTPException(status_code=404) | ||
|
||
return templates.TemplateResponse( | ||
"partials/version_list.html", | ||
{ | ||
"request": request, | ||
"project": project, | ||
"prompt_versions": project.prompt_versions, | ||
}, | ||
) | ||
|
||
|
||
@app.post("/projects/{project_name}/versions") | ||
async def create_version( | ||
request: Request, | ||
session: Annotated[Session, Depends(get_session)], | ||
project_name: str, | ||
prompt_template: str = Form(...), | ||
) -> RedirectResponse: | ||
"""Render the create_version.html template.""" | ||
project = session.exec( | ||
select(ProjectTable).where(ProjectTable.name == project_name) | ||
).first() | ||
|
||
if not project: | ||
raise HTTPException(status_code=404) | ||
|
||
latest_prompt_version = session.exec( | ||
select(PromptVersionTable).order_by("id") | ||
).first() | ||
|
||
prompt_version = PromptVersionTable( | ||
project_id=project.id, | ||
prompt_template=prompt_template, | ||
previous_version_id=latest_prompt_version.id if latest_prompt_version else None, | ||
) | ||
session.add(prompt_version) | ||
session.commit() | ||
session.flush() | ||
return RedirectResponse( | ||
url=f"/projects/{project_name}/versions/{prompt_version.id}", status_code=303 | ||
) | ||
|
||
|
||
@app.get( | ||
"/projects/{project_name}/versions/{prompt_version_id}", response_class=HTMLResponse | ||
) | ||
async def view_version( | ||
request: Request, | ||
session: Annotated[Session, Depends(get_session)], | ||
project_name: str, | ||
prompt_version_id: str, | ||
) -> HTMLResponse: | ||
"""Render the create_version.html template.""" | ||
prompt_version = session.exec( | ||
select(PromptVersionTable).where(PromptVersionTable.id == prompt_version_id) | ||
).first() | ||
|
||
if not prompt_version: | ||
raise HTTPException(status_code=404) | ||
|
||
@app.post("/submit", response_class=HTMLResponse) | ||
async def submit(request: Request, input_value: str = Form(...)) -> HTMLResponse: | ||
"""Render the result.html template.""" | ||
return templates.TemplateResponse( | ||
"partials/result.html", {"request": request, "input_value": input_value} | ||
"create_project.html", | ||
{ | ||
"request": request, | ||
"prompt_template": prompt_version.prompt_template, | ||
"project": prompt_version.project, | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"""This module initializes the models package.""" | ||
|
||
from .base_sql_model import BaseSQLModel | ||
from .projects import ProjectTable | ||
from .prompt_versions import PromptVersionTable | ||
|
||
__all__ = ["BaseSQLModel", "ProjectTable", "PromptVersionTable"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
"""Base SQLModel class for all SQLModel classes to inherit from""" | ||
|
||
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", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
"""Project model""" | ||
|
||
import datetime | ||
from typing import TYPE_CHECKING | ||
|
||
from sqlmodel import Field, Relationship | ||
|
||
from lilypad.app.models import BaseSQLModel | ||
|
||
from .table_names import PROJECT_TABLE_NAME | ||
|
||
if TYPE_CHECKING: | ||
from lilypad.app.models import PromptVersionTable | ||
|
||
|
||
class ProjectTable(BaseSQLModel, table=True): | ||
"""Project model""" | ||
|
||
__tablename__ = PROJECT_TABLE_NAME # type: ignore | ||
|
||
id: int | None = Field(default=None, primary_key=True) | ||
name: str = Field(nullable=False, unique=True) | ||
created_at: datetime.datetime = Field( | ||
default=datetime.datetime.now(datetime.UTC), nullable=False | ||
) | ||
prompt_versions: list["PromptVersionTable"] = Relationship( | ||
back_populates="project", cascade_delete=True | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"""Project model""" | ||
|
||
import datetime | ||
from typing import TYPE_CHECKING | ||
|
||
from sqlmodel import Field, Relationship | ||
|
||
from lilypad.app.models import BaseSQLModel | ||
|
||
from .table_names import PROJECT_TABLE_NAME, PROMPT_VERSION_TABLE_NAME | ||
|
||
if TYPE_CHECKING: | ||
from lilypad.app.models import ProjectTable | ||
|
||
|
||
class PromptVersionTable(BaseSQLModel, table=True): | ||
"""Prompt version model""" | ||
|
||
__tablename__ = PROMPT_VERSION_TABLE_NAME # type: ignore | ||
|
||
id: int | None = Field(default=None, primary_key=True) | ||
project_id: int | None = Field(default=None, foreign_key=f"{PROJECT_TABLE_NAME}.id") | ||
prompt_template: str = Field(nullable=False) | ||
created_at: datetime.datetime = Field( | ||
default=datetime.datetime.now(datetime.UTC), nullable=False | ||
) | ||
previous_version_id: int | None = Field( | ||
default=None, foreign_key=f"{PROMPT_VERSION_TABLE_NAME}.id" | ||
) | ||
|
||
project: "ProjectTable" = Relationship(back_populates="prompt_versions") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"""Table names for the database models.""" | ||
|
||
PROJECT_TABLE_NAME = "projects" | ||
PROMPT_VERSION_TABLE_NAME = "prompt_versions" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>HTMX Form</title> | ||
<script src="https://unpkg.com/htmx.org@2.0.0/dist/htmx.min.js"></script> | ||
<script | ||
src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" | ||
defer | ||
></script> | ||
</head> | ||
<body | ||
x-data="{ | ||
prompt_template: '{{ prompt_template }}', | ||
projectName: '{{ project.name }}', | ||
versionId: '{{ version_id }}' | ||
}" | ||
> | ||
<button hx-get="/" hx-target="body" hx-push-url="true">Back</button> | ||
<h1>{{ project.name }}</h1> | ||
<form | ||
hx-post="/projects/{{ project.name }}/versions" | ||
hx-target="body" | ||
hx-push-url="true" | ||
> | ||
<textarea | ||
name="prompt_template" | ||
rows="4" | ||
cols="50" | ||
x-model="prompt_template" | ||
></textarea> | ||
<br /> | ||
<button type="submit">Submit</button> | ||
</form> | ||
<div id="prompt-versions-list-container"> | ||
<h2>Prompt Versions:</h2> | ||
<ul | ||
id="prompt-versions-list" | ||
hx-get="/projects/{{ project.name }}/versions" | ||
hx-trigger="load" | ||
></ul> | ||
</div> | ||
</body> | ||
</html> |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{% for project in projects %} | ||
<li> | ||
<a href="projects/{{project.name}}" hx-push-url="true">{{ project.name }}</a> | ||
</li> | ||
{% endfor %} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.