Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
ade060f
add document endpoint and related code to the API
monicasmith463 Oct 7, 2025
dba0209
add boto3 and langchain to deps
monicasmith463 Oct 7, 2025
de52843
add textract to deps
monicasmith463 Oct 7, 2025
309245e
✨ Autogenerate frontend client
invalid-email-address Oct 7, 2025
7ff1e88
add aws key to test-backend.yml
monicasmith463 Oct 7, 2025
c6be71f
Merge branch 'backend-api' of https://github.com/monicasmith463/study…
monicasmith463 Oct 7, 2025
a64496c
add extractors test
monicasmith463 Oct 7, 2025
e75ae52
fix lint types-boto3
monicasmith463 Oct 7, 2025
55fbc7d
add aws and s3 secrets to env in docker-compose.yml
monicasmith463 Oct 7, 2025
d122216
update env in test-docker-compose
monicasmith463 Oct 7, 2025
5a21e77
fix env in playwright
monicasmith463 Oct 7, 2025
29e7b0a
add new secrets to .env
monicasmith463 Oct 7, 2025
e0e8975
skip flakey flakey_test_create_document for now
monicasmith463 Oct 8, 2025
cdc66ec
fix lint
monicasmith463 Oct 8, 2025
0fb34c7
Merge pull request #20 from monicasmith463/backend-api
monicasmith463 Oct 8, 2025
6aeef18
Merge remote-tracking branch 'upstream/master'
monicasmith463 Oct 8, 2025
5d53ab5
add the rest of the models to alembic and models.py
monicasmith463 Oct 8, 2025
b7e94b9
update conftest to include new models in session teardown
monicasmith463 Oct 8, 2025
ec2f362
update crud.py
monicasmith463 Oct 8, 2025
2fa55e9
exams endpoint working again
monicasmith463 Oct 8, 2025
b7fd21e
add OPENAI_API_KEY to pieline envs
monicasmith463 Oct 8, 2025
bb8e18a
add langchain_openai to deps
monicasmith463 Oct 8, 2025
3f4e815
✨ Autogenerate frontend client
invalid-email-address Oct 8, 2025
df69e69
exam_attempts endpoint working again
monicasmith463 Oct 8, 2025
b436ee7
Merge branch 'backend-api-2' of https://github.com/monicasmith463/stu…
monicasmith463 Oct 8, 2025
728f908
✨ Autogenerate frontend client
invalid-email-address Oct 8, 2025
f86ade3
try the flakey exam_attempts test again
monicasmith463 Oct 8, 2025
accd07a
Merge branch 'backend-api-2' of https://github.com/monicasmith463/stu…
monicasmith463 Oct 8, 2025
0939264
flakey tests are all passing now
monicasmith463 Oct 8, 2025
53864c9
Merge pull request #21 from monicasmith463/backend-api-2
monicasmith463 Oct 8, 2025
d002066
delete frontend dir entirely
monicasmith463 Oct 16, 2025
dd95a49
Add frontend boilerplate (bypass hooks)
monicasmith463 Oct 16, 2025
2bd21f2
docker-compose to start the frontend is working
monicasmith463 Oct 16, 2025
499a7c4
fix generate-client script
monicasmith463 Oct 16, 2025
b37b0e4
autogen files under /client from openapi
monicasmith463 Oct 16, 2025
365f766
fix axios build error for docker-compose build
monicasmith463 Oct 16, 2025
14e6d0e
Merge pull request #22 from monicasmith463/feature/frontend-new-boile…
monicasmith463 Oct 16, 2025
a3698c1
move (admin) dir to admin
monicasmith463 Oct 17, 2025
1c777ba
basic StaticHeader working
monicasmith463 Oct 17, 2025
79d90e5
document dropzone working for PDFs at /upload
monicasmith463 Oct 17, 2025
3f302cc
center the dropzone
monicasmith463 Oct 18, 2025
9d3f30d
button added to create exam
monicasmith463 Oct 18, 2025
86abafd
Merge pull request #23 from monicasmith463/feature/frontend-exam-gene…
monicasmith463 Oct 20, 2025
a25eb83
Merge remote-tracking branch 'upstream/master'
monicasmith463 Oct 20, 2025
7f55f75
add a SpinnerButton component
monicasmith463 Oct 21, 2025
4bebeab
exam form view with mocked data - no api
monicasmith463 Oct 21, 2025
68df355
fix lint err
monicasmith463 Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ SENTRY_DSN=
# Configure these with your own Docker registry images
DOCKER_IMAGE_BACKEND=backend
DOCKER_IMAGE_FRONTEND=frontend

AWS_ACCESS_KEY_ID=yourkey
AWS_SECRET_ACCESS_KEY=yoursecret
AWS_REGION=us-east-1
S3_BUCKET=your-bucket-name

OPENAI_API_KEY=yourkey
24 changes: 24 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ 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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# Set job outputs to values from filter step
outputs:
changed: ${{ steps.filter.outputs.changed }}
Expand All @@ -41,6 +47,12 @@ 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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
strategy:
matrix:
shardIndex: [1, 2, 3, 4]
Expand Down Expand Up @@ -92,6 +104,12 @@ 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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
Expand Down Expand Up @@ -123,6 +141,12 @@ 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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/test-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ 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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install uv
Expand Down
24 changes: 22 additions & 2 deletions .github/workflows/test-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,37 @@ on:
- synchronize

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 }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

steps:
- name: Checkout
uses: actions/checkout@v5
- name: Create .env for Docker Compose
run: |
echo "POSTGRES_USER=$POSTGRES_USER" >> backend/.env
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> backend/.env
echo "POSTGRES_DB=$POSTGRES_DB" >> backend/.env
echo "POSTGRES_PORT=$POSTGRES_PORT" >> backend/.env
echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> backend/.env
echo "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> backend/.env
echo "AWS_REGION=$AWS_REGION" >> backend/.env
echo "S3_BUCKET=$S3_BUCKET" >> backend/.env
echo "STACK_NAME=study-assistant" >> backend/.env

- run: docker compose build
- run: docker compose down -v --remove-orphans
- run: docker compose up -d --wait backend frontend adminer
- run: docker compose up -d --wait backend adminer frontend

- 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
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/
.DS_Store
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Add Question, Answer, Exam, ExamAttempt to the db

Revision ID: d29f99ac75e5
Revises: db14556d2858
Create Date: 2025-10-08 11:21:23.657380

"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes


# revision identifiers, used by Alembic.
revision = 'd29f99ac75e5'
down_revision = 'db14556d2858'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('exam',
sa.Column('title', sa.Text(), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('duration_minutes', sa.Integer(), nullable=True),
sa.Column('is_published', sa.Boolean(), nullable=False),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('owner_id', sa.Uuid(), nullable=False),
sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('examattempt',
sa.Column('score', sa.Float(), nullable=True),
sa.Column('is_complete', sa.Boolean(), nullable=False),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('exam_id', sa.Uuid(), nullable=False),
sa.Column('owner_id', sa.Uuid(), nullable=False),
sa.Column('completed_at', sa.DateTime(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['exam_id'], ['exam.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('question',
sa.Column('question', sa.Text(), nullable=False),
sa.Column('answer', sa.Text(), nullable=True),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('type', sa.Enum('MULTIPLE_CHOICE', 'TRUE_FALSE', 'SHORT_ANSWER', name='questiontype'), nullable=False),
sa.Column('options', sa.JSON(), nullable=True),
sa.Column('exam_id', sa.Uuid(), nullable=False),
sa.ForeignKeyConstraint(['exam_id'], ['exam.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('answer',
sa.Column('response', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('is_correct', sa.Boolean(), nullable=True),
sa.Column('explanation', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('attempt_id', sa.Uuid(), nullable=False),
sa.Column('question_id', sa.Uuid(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['attempt_id'], ['examattempt.id'], ),
sa.ForeignKeyConstraint(['question_id'], ['question.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('answer')
op.drop_table('question')
op.drop_table('examattempt')
op.drop_table('exam')
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Add Document model to the DB

Revision ID: db14556d2858
Revises: 1a31ce608336
Create Date: 2025-10-07 13:48:49.351591

"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes


# revision identifiers, used by Alembic.
revision = 'db14556d2858'
down_revision = '1a31ce608336'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('document',
sa.Column('filename', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False),
sa.Column('s3_url', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
sa.Column('s3_key', sqlmodel.sql.sqltypes.AutoString(length=1024), nullable=True),
sa.Column('content_type', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True),
sa.Column('size', sa.Integer(), nullable=True),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('owner_id', sa.Uuid(), nullable=False),
sa.Column('extracted_text', sa.Text(), nullable=True),
sa.Column('chunk_count', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('documentchunk',
sa.Column('text', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('id', sa.Uuid(), nullable=False),
sa.Column('document_id', sa.Uuid(), nullable=False),
sa.Column('size', sa.Integer(), nullable=False),
sa.Column('type', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.ForeignKeyConstraint(['document_id'], ['document.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('documentchunk')
op.drop_table('document')
# ### end Alembic commands ###
14 changes: 13 additions & 1 deletion backend/app/api/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
from fastapi import APIRouter

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

api_router = APIRouter()
api_router.include_router(documents.router)
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(exams.router)
api_router.include_router(exam_attempts.router)


if settings.ENVIRONMENT == "local":
Expand Down
Loading
Loading