Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
5cc0889
✨ Refactor item management to document management in API and models
monicasmith463 Jul 18, 2025
540461c
✨ Update document model and add S3 upload functionality
monicasmith463 Jul 25, 2025
f41dfd2
✨ Add S3 file upload functionality and update document creation process
monicasmith463 Jul 28, 2025
e9e87af
✨ Add Python version file and expose PostgreSQL port in Docker Compose
monicasmith463 Jul 28, 2025
fea3bda
skip using alembic for now
monicasmith463 Jul 28, 2025
f084486
✨ Remove item management API routes and associated tests
monicasmith463 Jul 28, 2025
24bb157
✨ Remove obsolete Alembic migration scripts for cascade delete relati…
monicasmith463 Jul 28, 2025
8fb03d6
✨ Add .env to .gitignore to prevent sensitive information from being …
monicasmith463 Jul 28, 2025
26bd7dd
✨ Add text extraction functionality from S3 files and save to database
monicasmith463 Jul 28, 2025
ebb8965
✨ Add extracted_text field to Document model and implement text extra…
monicasmith463 Jul 29, 2025
a20ace4
✨ Add text extraction dependencies and integrate extraction in docume…
monicasmith463 Jul 29, 2025
a140f2e
Merge branch 'master' of https://github.com/monicasmith463/study-assi…
monicasmith463 Aug 4, 2025
cd7d024
don't do alembic migrations for now
monicasmith463 Aug 4, 2025
bcdb323
run ruff to fix linter build
monicasmith463 Aug 4, 2025
bcd6c96
remove add-to-project job from the build
monicasmith463 Aug 4, 2025
30a4777
Merge pull request #1 from monicasmith463/infra/remove-alembic-migration
monicasmith463 Aug 4, 2025
b53f90f
undo delete backend/app/alembic/versions/
monicasmith463 Aug 4, 2025
9012074
Merge branch 'master' of https://github.com/monicasmith463/study-assi…
monicasmith463 Aug 4, 2025
8040455
✨ Autogenerate frontend client
invalid-email-address Aug 4, 2025
59b3d11
fix lint err in model DocumentBase make fieldds optional
monicasmith463 Aug 4, 2025
9509aeb
add boto3-stubs
monicasmith463 Aug 5, 2025
adc5119
convert UUID to a string in documents.py
monicasmith463 Aug 5, 2025
d8efa80
fix return type annotation
monicasmith463 Aug 5, 2025
b7bbb80
Merge branch 'feature/file-upload' of https://github.com/monicasmith4…
monicasmith463 Aug 5, 2025
7b21986
removed unused type ignore
monicasmith463 Aug 5, 2025
97fd600
Update backend/app/api/routes/documents.py
monicasmith463 Aug 5, 2025
3bcc444
fix: remove local development path from requirements.txt
devloai[bot] Aug 5, 2025
10ae893
fix: configure S3 client with proper AWS credentials from settings
devloai[bot] Aug 5, 2025
3405175
Update backend/app/s3.py
monicasmith463 Aug 5, 2025
5864e66
remove requirements.txt and python-version
monicasmith463 Aug 5, 2025
59b588d
merge
monicasmith463 Aug 5, 2025
a2a920f
fix lint errors
monicasmith463 Aug 5, 2025
5e6b6a2
Delete backend/requirements.txt
monicasmith463 Aug 5, 2025
ed1ce65
Delete requirements.txt
monicasmith463 Aug 5, 2025
678e393
Update .env
monicasmith463 Aug 5, 2025
f66e128
add new AWS secrets for test workflow
monicasmith463 Aug 5, 2025
8ab5719
update deploy-staging
monicasmith463 Aug 5, 2025
344ce94
update docker-compose
monicasmith463 Aug 5, 2025
62c48e8
add also to backend env
monicasmith463 Aug 5, 2025
9dd39d5
update env secrets in the test-backend.yml
monicasmith463 Aug 5, 2025
f57686b
update generate-client.yml, playwright.yml, test-docker-compose.yml
monicasmith463 Aug 5, 2025
270e13a
✨ Autogenerate frontend client
invalid-email-address Aug 5, 2025
4118279
update playwirght.yml again
monicasmith463 Aug 5, 2025
2e32d50
Merge branch 'feature/file-upload' of https://github.com/monicasmith4…
monicasmith463 Aug 5, 2025
aaef247
add Item back into models.py for now
monicasmith463 Aug 5, 2025
5c6cfbb
make Item model inactive
monicasmith463 Aug 5, 2025
4c05f36
revert changes to model
monicasmith463 Aug 5, 2025
eb4ac0a
safe filename
monicasmith463 Aug 5, 2025
0b107e2
run ruff lint fixes
monicasmith463 Aug 5, 2025
28e3662
ruff format app
monicasmith463 Aug 5, 2025
54925db
Merge pull request #3 from monicasmith463/feature/file-upload
monicasmith463 Aug 5, 2025
6607321
merge master
monicasmith463 Aug 5, 2025
7f943ac
Update pyproject.toml
monicasmith463 Aug 5, 2025
96e865d
fix select statement in extractors for lint error
monicasmith463 Aug 5, 2025
3dfe720
fix more lint errors
monicasmith463 Aug 5, 2025
400591f
fix extract test:
monicasmith463 Aug 5, 2025
410e6b9
refactor extractors to use S3 text extraction function and update dep…
monicasmith463 Aug 6, 2025
fd5c466
Comment out frontend service configuration in Docker Compose files
monicasmith463 Aug 6, 2025
687a85d
take frontend stuff out of the build so it passes
monicasmith463 Aug 6, 2025
66262ed
skip playwright.yml for now
monicasmith463 Aug 6, 2025
d3e2ef2
Comment out playwright service in Docker Compose files and add port m…
monicasmith463 Aug 6, 2025
42257e2
bad spacing in docker-compose.yml
monicasmith463 Aug 6, 2025
b4b7e1e
Update GitHub Actions workflow to only start backend and adminer serv…
monicasmith463 Aug 6, 2025
55be41e
Merge pull request #8 from monicasmith463/infra/turn-off-frontend
monicasmith463 Aug 6, 2025
0533dc2
Merge branch 'master' of https://github.com/monicasmith463/study-assi…
monicasmith463 Aug 6, 2025
d5baef4
Set default AWS region and update test to use correct extractor function
monicasmith463 Aug 7, 2025
6c191c8
Add s3_key field to DocumentBase model and include it in document cre…
monicasmith463 Aug 7, 2025
23ee3cd
✨ Autogenerate frontend client
invalid-email-address Aug 7, 2025
6fa7ebd
Refactor S3 text extraction to simplify function signature and remove…
monicasmith463 Aug 7, 2025
e7304d5
Merge branch 'feature/extract-text' of https://github.com/monicasmith…
monicasmith463 Aug 7, 2025
07725c3
Refactor extract_text_and_save_to_db to use s3_key instead of s3_url
monicasmith463 Aug 7, 2025
5c55172
Update test_extract_text_and_save_to_db to use keyword argument for s…
monicasmith463 Aug 7, 2025
8193641
Refactor imports and clean up code formatting in extractors, models, …
monicasmith463 Aug 7, 2025
02e4b8c
Merge pull request #5 from monicasmith463/feature/extract-text
monicasmith463 Aug 7, 2025
b06f337
Refactor sidebar and route management; remove items route and update …
monicasmith463 Aug 8, 2025
d761360
Enhance docker-compose configuration by uncommenting frontend and pla…
monicasmith463 Aug 8, 2025
e2c624c
✨ Autogenerate frontend client
invalid-email-address Aug 8, 2025
d4fe711
Refactor code formatting and update .gitignore entries for consistency
monicasmith463 Aug 8, 2025
ea813bd
reformat with pretter
monicasmith463 Aug 8, 2025
d9fde6c
accidentally took ruff out of pre-commit-config.yml
monicasmith463 Aug 8, 2025
8663bb8
✨ Autogenerate frontend client
invalid-email-address Aug 8, 2025
65efaf1
Merge pull request #9 from monicasmith463/bug/frontend-item-ref-err
monicasmith463 Aug 8, 2025
5cf5748
✨ Add Dropzone and AddDocument components; update sidebar and routing…
monicasmith463 Aug 10, 2025
05d8283
✨ Refactor AddDocument component to integrate Dropzone functionality;…
monicasmith463 Aug 10, 2025
d20c33c
✨ Update @chakra-ui/react dependency to version 3.24.2; remove unused…
monicasmith463 Aug 10, 2025
8883a75
✨ Integrate file upload functionality in AddDocument component; enhan…
monicasmith463 Aug 10, 2025
0b8d2ea
🔧 Fix background task parameter in create_document function to use 'k…
monicasmith463 Aug 10, 2025
9c36d80
✨ Enhance AddDocument component with dialog for file upload; integrat…
monicasmith463 Aug 11, 2025
7bebd96
✨ Create document retrieval logic in API; update endpoint to use UUID…
monicasmith463 Aug 11, 2025
62281e1
✨ Implement document retrieval endpoints; enhance permission checks a…
monicasmith463 Aug 11, 2025
76c2de4
✨ Add update document endpoint; implement permission checks and updat…
monicasmith463 Aug 11, 2025
7889366
✨ Add delete document endpoint; implement permission checks and respo…
monicasmith463 Aug 11, 2025
88b394b
✨ Autogen Swagger API types for consistency; standardize formatting a…
monicasmith463 Aug 11, 2025
38c1f1e
✨ Add document management features; implement delete and edit functio…
monicasmith463 Aug 11, 2025
98ac43d
✨ Remove deprecated documents2 route; streamline route management and…
monicasmith463 Aug 11, 2025
963c3b7
✨ Autogenerate frontend client
invalid-email-address Aug 11, 2025
9f2c484
✨ Remove EditDocument component; simplify document actions menu and i…
monicasmith463 Aug 11, 2025
9e3d2a5
✨ Refactor document table; update column headers and improve data dis…
monicasmith463 Aug 11, 2025
d999000
Merge branch 'feature/frontend-uploader' of https://github.com/monica…
monicasmith463 Aug 11, 2025
0d4d038
✨ Update route definitions for consistency and improve document table…
monicasmith463 Aug 11, 2025
ab40aff
✨ Add Question model and relationship to User; enhance data structure
monicasmith463 Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/workflows/add-to-project.yml

This file was deleted.

4 changes: 4 additions & 0 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
EMAILS_FROM_EMAIL: ${{ secrets.EMAILS_FROM_EMAIL }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
steps:
- name: Checkout
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
EMAILS_FROM_EMAIL: ${{ secrets.EMAILS_FROM_EMAIL }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
steps:
- name: Checkout
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/generate-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ jobs:
permissions:
contents: write
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
steps:
# For PRs from forks
- uses: actions/checkout@v4
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ on:
jobs:
changes:
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
# Set job outputs to values from filter step
outputs:
changed: ${{ steps.filter.outputs.changed }}
Expand All @@ -41,6 +46,11 @@ jobs:
if: ${{ needs.changes.outputs.changed == 'true' }}
timeout-minutes: 60
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
strategy:
matrix:
shardIndex: [1, 2, 3, 4]
Expand Down Expand Up @@ -92,6 +102,11 @@ jobs:
# Merge reports after playwright-tests, even if some shards have failed
if: ${{ !cancelled() && needs.changes.outputs.changed == 'true' }}
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -123,6 +138,11 @@ jobs:
needs:
- test-playwright
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/test-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ on:
jobs:
test-backend:
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
16 changes: 12 additions & 4 deletions .github/workflows/test-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,22 @@ jobs:

test-docker-compose:
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
steps:
- name: Checkout
uses: actions/checkout@v4
- run: docker compose build
- run: docker compose down -v --remove-orphans
- run: docker compose up -d --wait backend frontend adminer
# TODO: Bring frontend back up when you fix the bug
# - run: docker compose up -d --wait backend frontend adminer
- run: docker compose up -d --wait backend adminer

- name: Test backend is up
run: curl http://localhost:8000/api/v1/utils/health-check
- name: Test frontend is up
run: curl http://localhost:5173
- run: docker compose down -v --remove-orphans
# - name: Test frontend is up
# run: curl http://localhost:5173
# - run: docker compose down -v --remove-orphans
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules/
/playwright-report/
/blob-report/
/playwright/.cache/
.env
20 changes: 19 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,32 @@ repos:
)$
- id: trailing-whitespace
exclude: ^frontend/src/client/.*
# - repo: https://github.com/pre-commit/mirrors-eslint
# rev: v8.53.0
# hooks:
# - id: eslint
# files: \.[jt]sx?$
# types: [file]
# additional_dependencies:
# - [email protected]
# - [email protected]
# - [email protected]
# - "@typescript-eslint/[email protected]"
# - "@typescript-eslint/[email protected]"
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.2.2
hooks:
- id: ruff
args:
- --fix
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: prettier
files: \.(ts|tsx)$
additional_dependencies:
- [email protected]
ci:
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate
4 changes: 2 additions & 2 deletions backend/app/api/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from fastapi import APIRouter

from app.api.routes import items, login, private, users, utils
from app.api.routes import documents, login, private, users, utils
from app.core.config import settings

api_router = APIRouter()
api_router.include_router(login.router)
api_router.include_router(users.router)
api_router.include_router(utils.router)
api_router.include_router(items.router)
api_router.include_router(documents.router)


if settings.ENVIRONMENT == "local":
Expand Down
145 changes: 145 additions & 0 deletions backend/app/api/routes/documents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import uuid
from typing import Any

from fastapi import APIRouter, BackgroundTasks, File, HTTPException, UploadFile
from sqlmodel import func, select

from app.api.deps import CurrentUser, SessionDep
from app.core.extractors import extract_text_and_save_to_db
from app.models import (
Document,
DocumentCreate,
DocumentPublic,
DocumentsPublic,
DocumentUpdate,
Message,
)
from app.s3 import generate_s3_url, upload_file_to_s3

router = APIRouter(prefix="/documents", tags=["documents"])


@router.post("/", response_model=DocumentPublic)
def create_document(
*,
session: SessionDep,
current_user: CurrentUser,
background_tasks: BackgroundTasks, # noqa: ARG001
file: UploadFile = File(...),
) -> Any:
key = None
try:
key = upload_file_to_s3(file, str(current_user.id))
except Exception as e:
raise HTTPException(500, f"Failed to upload file. Error: {str(e)}")

try:
url = generate_s3_url(key)
except Exception:
raise HTTPException(500, f"Could not generate URL for file key: {key}")

document_in = DocumentCreate(
filename=file.filename,
content_type=file.content_type,
size=file.size,
s3_url=url,
s3_key=key,
)

document = Document.model_validate(
document_in, update={"owner_id": current_user.id}
)

session.add(document)
session.commit()
session.refresh(document)

# 3. Kick off background job
print("Document created, starting background task...")
background_tasks.add_task(extract_text_and_save_to_db, key, str(document.id))
return document


@router.get("/{id}", response_model=DocumentPublic)
def read_document(session: SessionDep, current_user: CurrentUser, id: uuid.UUID) -> Any:
"""
Get document by ID.
"""
document = session.get(Document, id)
if not document:
raise HTTPException(status_code=404, detail="Document not found")
if not current_user.is_superuser and (document.owner_id != current_user.id):
raise HTTPException(status_code=400, detail="Not enough permissions")
return document


@router.get("/", response_model=DocumentsPublic)
def read_documents(
session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100
) -> Any:
"""
Retrieve documents.
"""

if current_user.is_superuser:
count_statement = select(func.count()).select_from(Document)
count = session.exec(count_statement).one()
statement = select(Document).offset(skip).limit(limit)
documents = session.exec(statement).all()
else:
count_statement = (
select(func.count())
.select_from(Document)
.where(Document.owner_id == current_user.id)
)
count = session.exec(count_statement).one()
statement = (
select(Document)
.where(Document.owner_id == current_user.id)
.offset(skip)
.limit(limit)
)
documents = session.exec(statement).all()

return DocumentsPublic(data=documents, count=count)


@router.put("/{id}", response_model=DocumentPublic)
def update_document(
*,
session: SessionDep,
current_user: CurrentUser,
id: uuid.UUID,
document_in: DocumentUpdate,
) -> Any:
"""
Update an document.
"""
document = session.get(Document, id)
if not document:
raise HTTPException(status_code=404, detail="Document not found")
if not current_user.is_superuser and (document.owner_id != current_user.id):
raise HTTPException(status_code=400, detail="Not enough permissions")
update_dict = document_in.model_dump(exclude_unset=True)
document.sqlmodel_update(update_dict)
session.add(document)
session.commit()
session.refresh(document)
return document


@router.delete("/{id}")
def delete_document(
session: SessionDep, current_user: CurrentUser, id: uuid.UUID
) -> Message:
"""
Delete an document.
"""
document = session.get(Document, id)
if not document:
raise HTTPException(status_code=404, detail="Document not found")
if not current_user.is_superuser and (document.owner_id != current_user.id):
raise HTTPException(status_code=400, detail="Not enough permissions")
session.delete(document)
session.commit()
return Message(message="Document deleted successfully")
Loading
Loading