Skip to content

Commit

Permalink
Merge pull request #28 from nattvara/feature/list-admin-rooms
Browse files Browse the repository at this point in the history
Show courses user administrates in navbar
  • Loading branch information
nattvara authored Apr 21, 2024
2 parents 457aff8 + f59f53d commit 620e052
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 1 deletion.
31 changes: 31 additions & 0 deletions gui/api/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { HttpError, getSessionId, makeUrl } from "@/api/http";

export interface Course {
canvas_id: string;
language: string;
name: string;
}

export interface Courses {
courses: Course[];
}

export async function fetchCourses(): Promise<Courses> {
const sessionCookie = getSessionId() as string;

const response = await fetch(makeUrl(`/admin/courses`), {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-Session-ID": sessionCookie,
},
});

if (!response.ok) {
const errorBody = await response.json();
throw new HttpError(response, errorBody, response.status);
}

const data = (await response.json()) as Courses;
return data;
}
39 changes: 39 additions & 0 deletions gui/components/navigation/CourseList/CourseList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Button, SimpleGrid, Title } from "@mantine/core";
import { useQuery } from "@tanstack/react-query";

import { fetchCourses } from "@/api/admin";

import styles from "./styles.module.css";

export default function CourseList() {
const coursesQuery = useQuery({
queryKey: ["courses"],
queryFn: () => fetchCourses(),
});

if (!coursesQuery.data) {
return <></>;
}

if (coursesQuery.data.courses.length === 0) {
return <></>;
}

return (
<SimpleGrid cols={1} className={styles.root}>
<Title order={4}>Courses</Title>
{coursesQuery.data.courses.map((course) => (
<Button
key={course.canvas_id}
variant="light"
size="xs"
component="a"
href={`/course/${course.canvas_id}/chats`}
target="_blank"
>
{course.name}
</Button>
))}
</SimpleGrid>
);
}
4 changes: 4 additions & 0 deletions gui/components/navigation/CourseList/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

.root {
padding-top: 20px;
}
4 changes: 4 additions & 0 deletions gui/components/navigation/HeaderNavbar/HeaderNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { useTranslation } from "next-i18next";
import { useRouter } from "next/router";
import { MouseEventHandler, useEffect } from "react";

import { CourseList } from "@/components/navigation";

import { getSession } from "@/api/session";

const ContactEmail = "[email protected]";
Expand Down Expand Up @@ -68,6 +70,8 @@ export default function HeaderNavbar(props: HeaderNavbarProps) {
<Button leftSection={<IconMail size={14} />} variant="default" component="a" href={`mailto:${ContactEmail}`}>
{t("header.contact_researcher")}
</Button>

<CourseList />
</AppShell.Navbar>
</>
);
Expand Down
3 changes: 2 additions & 1 deletion gui/components/navigation/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CourseList from "./CourseList/CourseList";
import HeaderNavbar from "./HeaderNavbar/HeaderNavbar";

export { HeaderNavbar };
export { HeaderNavbar, CourseList };
2 changes: 2 additions & 0 deletions http_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
sessions,
health,
index,
admin,
chat,
)
from config.logger import log
Expand All @@ -29,6 +30,7 @@ def get_app():
app.include_router(chat.router)
app.include_router(health.router)
app.include_router(feedback.router)
app.include_router(admin.router)

return app

Expand Down
41 changes: 41 additions & 0 deletions http_api/routers/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import List

from fastapi import APIRouter, Depends
from pydantic import BaseModel

from db.actions.course import find_course_by_canvas_id
from http_api.auth import get_current_session
from config.logger import log
from db.models import Session

router = APIRouter()


class Course(BaseModel):
canvas_id: str
language: str
name: str


class CourseResponse(BaseModel):
courses: List[Course]


@router.get(
'/admin/courses',
dependencies=[Depends(get_current_session)],
response_model=CourseResponse
)
async def get_courses_user_can_administrate(session: Session = Depends(get_current_session)) -> CourseResponse:
courses = []
for canvas_id in session.admin_courses:
course = find_course_by_canvas_id(canvas_id)
if course is None:
log().warning(f"found course id that doesn't exist: {canvas_id}, in session: {session.public_id}")
continue
courses.append(Course(
canvas_id=course.canvas_id,
language=course.language,
name=course.name
))
return CourseResponse(courses=courses)
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ def __init__(self, session: Session):
consent=True,
default_llm_model_name=LLMModel.MISTRAL_7B_INSTRUCT,
default_index_type=IndexType.NO_INDEX,
admin_courses=[]
)
valid_session.save()

Expand Down
12 changes: 12 additions & 0 deletions tests/http_api/admin_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

def test_user_courses_user_can_administrate_are_returned_in_list_of_courses(
api_client,
valid_course,
authenticated_session,
):
authenticated_session.session.admin_courses.append(valid_course.canvas_id)
authenticated_session.session.save()

response = api_client.get('/admin/courses', headers=authenticated_session.headers)
assert response.status_code == 200
assert response.json()['courses'][0]['canvas_id'] == valid_course.canvas_id

0 comments on commit 620e052

Please sign in to comment.