Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Graph Builder and Chat Capability #2

Merged
merged 21 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
008d6d5
frontend: Update node version in .nvmrc
StreetLamb Apr 14, 2024
7f88c98
frontend: generate client based on updated openapi.json
StreetLamb Apr 14, 2024
56e7ba8
Fix update_team endpoint request type
StreetLamb Apr 14, 2024
6245e20
frontend: Add teams page
StreetLamb Apr 14, 2024
09a4030
Add biome.json to root so vscode respects the config when formatting …
StreetLamb Apr 14, 2024
c5958e1
frontend: Add team page and update sidebar to show teams button
StreetLamb Apr 15, 2024
1d99a55
backend: Add team member route
StreetLamb Apr 16, 2024
abe07f6
frontend: Add autogen code for frontend. Rename backend endpoint
StreetLamb Apr 16, 2024
a1931cc
Add position columns in member model
StreetLamb Apr 17, 2024
53c4576
backend: Allow deleted team to cascade delete it's members
StreetLamb Apr 18, 2024
3e42d38
Add source column to members table
StreetLamb Apr 18, 2024
de52420
Fix member endpoint urls
StreetLamb Apr 18, 2024
f5ff4c9
backend: Create root member when creating team
StreetLamb Apr 19, 2024
8b1fa75
frontend: Add team page to create, update and delete team members via…
StreetLamb Apr 19, 2024
48b7935
Validate regex for team and member names
StreetLamb Apr 21, 2024
2290ace
Rename member to workers
StreetLamb Apr 21, 2024
e14e849
Enable streaming of team's response and displaying on frontend
StreetLamb Apr 21, 2024
5fb071f
backend: Fix convert_team_to_dict logic
StreetLamb Apr 21, 2024
7c46d37
backend: Use ruff to format files
StreetLamb Apr 21, 2024
bcedcf3
Make team name and (member name, team id) unique. Remove the need for…
StreetLamb Apr 22, 2024
a82191a
frontend: Fix MessageBox
StreetLamb Apr 22, 2024
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
49 changes: 23 additions & 26 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug FastAPI Project backend: Python Debugger",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": [
"app.main:app",
"--reload"
],
"cwd": "${workspaceFolder}/backend",
"jinja": true,
"envFile": "${workspaceFolder}/.env",
},
{
"type": "chrome",
"request": "launch",
"name": "Debug Frontend: Launch Chrome against http://localhost:5173",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/frontend"
},
]
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug FastAPI Project backend: Python Debugger",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": ["app.main:app", "--reload"],
"cwd": "${workspaceFolder}/backend",
"jinja": true,
"envFile": "${workspaceFolder}/.env"
},
{
"type": "chrome",
"request": "launch",
"name": "Debug Frontend: Launch Chrome against http://localhost:5173",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/frontend"
}
]
}
5 changes: 4 additions & 1 deletion backend/app/api/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from fastapi import APIRouter

from app.api.routes import items, login, users, utils, teams
from app.api.routes import items, login, members, teams, users, utils

api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(items.router, prefix="/items", tags=["items"])
api_router.include_router(teams.router, prefix="/teams", tags=["teams"])
api_router.include_router(
members.router, prefix="/teams/{team_id}/members", tags=["members"]
)
205 changes: 205 additions & 0 deletions backend/app/api/routes/members.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
from typing import Any

from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import func, select

from app.api.deps import CurrentUser, SessionDep
from app.models import (
Member,
MemberCreate,
MemberOut,
MembersOut,
MemberUpdate,
Message,
Team,
)

router = APIRouter()


def validate_unique_name_in_team(
session: SessionDep, team_id: int, id: int, member_in: MemberCreate | MemberUpdate
):
"""Check if (name, team_id) is unique"""
if member_in.name is None:
return
statement = select(Member).where(
Member.name == member_in.name,
Member.belongs_to == team_id,
Member.id != id,
)
member_unique = session.exec(statement).first()
if member_unique:
raise HTTPException(
status_code=400, detail="Member with this name already exists"
)


@router.get("/", response_model=MembersOut)
def read_members(
session: SessionDep,
current_user: CurrentUser,
team_id: int,
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve members from team.
"""
# TODO: Use new way of getting members from teams. Get team first then use team.members
if current_user.is_superuser:
count_statement = select(func.count()).select_from(Member)
count = session.exec(count_statement).one()
statement = (
select(Member).where(Member.belongs_to == team_id).offset(skip).limit(limit)
)
members = session.exec(statement).all()
else:
count_statement = (
select(func.count())
.select_from(Member)
.join(Team)
.where(Team.owner_id == current_user.id, Member.belongs_to == team_id)
)
count = session.exec(count_statement).one()
statement = (
select(Member)
.join(Team)
.where(Team.owner_id == current_user.id, Member.belongs_to == team_id)
.offset(skip)
.limit(limit)
)
members = session.exec(statement).all()

return MembersOut(data=members, count=count)


@router.get("/{id}", response_model=MemberOut)
def read_member(
session: SessionDep, current_user: CurrentUser, team_id: int, id: int
) -> Any:
"""
Get member by ID.
"""
if current_user.is_superuser:
statement = (
select(Member)
.join(Team)
.where(Member.id == id, Member.belongs_to == team_id)
)
member = session.exec(statement).first()
else:
statement = (
select(Member)
.join(Team)
.where(
Member.id == id,
Member.belongs_to == team_id,
Team.owner_id == current_user.id,
)
)
member = session.exec(statement).first()

if not member:
raise HTTPException(status_code=404, detail="Member not found")
return member


@router.post("/", response_model=MemberOut)
def create_member(
*,
session: SessionDep,
current_user: CurrentUser,
team_id: int,
member_in: MemberCreate,
_: bool = Depends(validate_unique_name_in_team),
) -> Any:
"""
Create new member.
"""
if not current_user.is_superuser:
team = session.get(Team, team_id)
if team.owner_id != current_user.id:
raise HTTPException(status_code=400, detail="Not enough permissions")
member = Member.model_validate(member_in, update={"belongs_to": team_id})
session.add(member)
session.commit()
session.refresh(member)
return member


@router.put("/{id}", response_model=MemberOut)
def update_member(
*,
session: SessionDep,
current_user: CurrentUser,
team_id: int,
id: int,
member_in: MemberUpdate,
_: bool = Depends(validate_unique_name_in_team),
) -> Any:
"""
Update a member.
"""
if current_user.is_superuser:
statement = (
select(Member)
.join(Team)
.where(Member.id == id, Member.belongs_to == team_id)
)
member = session.exec(statement).first()
else:
statement = (
select(Member)
.join(Team)
.where(
Member.id == id,
Member.belongs_to == team_id,
Team.owner_id == current_user.id,
)
)
member = session.exec(statement).first()

if not member:
raise HTTPException(status_code=404, detail="Member not found")

update_dict = member_in.model_dump(exclude_unset=True)
member.sqlmodel_update(update_dict)
session.add(member)
session.commit()
session.refresh(member)
return member


@router.delete("/{id}")
def delete_member(
session: SessionDep, current_user: CurrentUser, team_id: int, id: int
) -> Message:
"""
Delete a member.
"""
if current_user.is_superuser:
statement = (
select(Member)
.join(Team)
.where(Member.id == id, Member.belongs_to == team_id)
)
member = session.exec(statement).first()
else:
statement = (
select(Member)
.join(Team)
.where(
Member.id == id,
Member.belongs_to == team_id,
Team.owner_id == current_user.id,
)
)
member = session.exec(statement).first()

if not member:
raise HTTPException(status_code=404, detail="Member not found")

session.delete(member)
session.commit()
return Message(message="Member deleted successfully")
Loading
Loading