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

Code documentation #197

Merged
merged 4 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions frontend/__test__/AccountMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ describe('AccountMenu', () => {
fireEvent.click(screen.getByRole('button'));
const menu = screen.getByRole('menu');
expect(menu).toBeVisible();
fireEvent.click(screen.getByRole('menuitem', {name: 'settings'}));
expect(menu).not.toBeVisible();
});


Expand Down
10 changes: 0 additions & 10 deletions frontend/__test__/course_components/CancelButton.test.tsx

This file was deleted.

22 changes: 8 additions & 14 deletions frontend/app/[locale]/components/AccountMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ import {useEffect, useState} from "react";
const backend_url = process.env['NEXT_PUBLIC_BACKEND_URL'];

export default function AccountMenu() {
/*
* Account menu component, used to display the user's name and a dropdown menu with options to go to the profile page and logout(right side of the navbar)
* */
const [user, setUser] = useState<UserData | null>(null);
const [error, setError] = useState<APIError | null>(null);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const { t } = useTranslation()

useEffect(() => {


const fetchCourses = async () => {
try{
setUser(await getUserData());
Expand All @@ -39,26 +42,23 @@ export default function AccountMenu() {
fetchCourses();
}, []);



const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
//Utility & navigation functions
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
//TODO: Handle settings and My profile actions!!
setAnchorEl(null);
};

const toProfile = () => {
window.location.href = '/profile'
}
};

const handleLogout = () => {
setAnchorEl(null);
window.location.href = backend_url + "/auth/logout";
};

return (
<React.Fragment>
<Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}>
Expand Down Expand Up @@ -108,12 +108,6 @@ export default function AccountMenu() {
<Avatar /> {t('my_profile')}
</MenuItem>
<Divider />
<MenuItem onClick={handleClose}>
<ListItemIcon>
<Settings fontSize="small" />
</ListItemIcon>
{t('settings')}
</MenuItem>
<MenuItem onClick={handleLogout}>
<ListItemIcon>
<Logout fontSize="small" />
Expand Down
6 changes: 5 additions & 1 deletion frontend/app/[locale]/components/AddButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { Button } from '@mui/material';
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import {useTranslation} from "react-i18next";

//TODO: route to add project page
function AddButton({translationkey, href} : {translationkey: string, href : string|undefined}){
/*
* General add button component
* @param translationkey: The key of the translation in the i18n file
* @param href: The href of the button
* */
const { t } = useTranslation()

return(
Expand Down
6 changes: 5 additions & 1 deletion frontend/app/[locale]/components/AddProjectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ interface EditCourseButtonProps{
}

const AddProjectButton = ({course_id}: EditCourseButtonProps) => {
/*
* Specific add project button component
* @param course_id: The id of the course to which the project will be added
* */
const {t} = useTranslation();
const [user, setUser] = useState<UserData | null>(null);
const [loading, setLoading] = useState(true);
Expand Down Expand Up @@ -38,7 +42,7 @@ const AddProjectButton = ({course_id}: EditCourseButtonProps) => {
}}
/> :
<>
{user?.role !== 3 && (
{user?.role !== 3 && ( // If the user is not a student
<Button
variant="contained"
color="secondary"
Expand Down
6 changes: 5 additions & 1 deletion frontend/app/[locale]/components/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
'use client'
import React from 'react';
import {Button} from "@mui/material";
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
Expand All @@ -10,6 +9,11 @@ interface BackButtonProps {

// back button has to take the destination as a prop and navigate to it
export default function BackButton({destination, text}: BackButtonProps) {
/*
* general back button component
* @param destination: The destination of the button
* @param text: The text of the button
* */

return (
<Button
Expand Down
4 changes: 3 additions & 1 deletion frontend/app/[locale]/components/CASButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const backend_url = process.env['NEXT_PUBLIC_BACKEND_URL'];
const redirect_url = process.env['NEXT_PUBLIC_REDIRECT_URL'];

const CASButton = () => {
/*
* Button to login with CAS
* */
const handleCASLogin = (): void => {
// Implement CAS login logic here
console.log('Login with CAS');
window.location.href = backend_url + "/microsoft/to-auth-redirect?next=" + redirect_url + "/home"
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/app/[locale]/components/CopyToClipboardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ interface CopyToClipboardButtonProps {
}

const CopyToClipboardButton = ({text}: CopyToClipboardButtonProps) => {
/*
* General Button that copies text to clipboard.
* @param text: text that has to be copied to clipboard.
* */
const [open, setOpen] = useState(false);
const {t} = useTranslation();

Expand Down
8 changes: 6 additions & 2 deletions frontend/app/[locale]/components/CourseBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ interface CourseBannerProps {
}

const CourseBanner = ({course_id}: CourseBannerProps) => {
/*
* Banner component displayed in the course details page
* @param course_id: id of the course.
* */
const [user, setUser] = useState<UserData | null>(null);
const [course, setCourse] = useState<Course | null>(null);
const [error, setError] = useState<APIError | null>(null);
Expand Down Expand Up @@ -77,10 +81,10 @@ const CourseBanner = ({course_id}: CourseBannerProps) => {
textOverflow: 'ellipsis',
}}
>
{course?.name + (course?.year === null ? "" : " " + course?.year)}
{course?.name + (course?.year === null ? "" : " " + course?.year) /*Display the course name + the year of the course*/}
</Typography>
</Box>
{user?.role !== 3 ? (
{user?.role !== 3 ? ( //Do not display edit button if the user is a student.
<Box
display="flex"
justifyContent={{ xs: 'center', sm: 'flex-start' }}
Expand Down
6 changes: 5 additions & 1 deletion frontend/app/[locale]/components/CourseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import AccesAlarm from '@mui/icons-material/AccessAlarm';
import Person from '@mui/icons-material/Person';

const CourseCard = ({params: {course}}: { params: { course: Course } }) => {
/*
* Card component displayed in the home page that represent a course
* @param course: Course object of the course that is to be displayed in the card
* */
const [projects, setProjects] = useState<Project[]>([]);
const [last_submission, setSubmission] =
useState<Submission>({
Expand Down Expand Up @@ -44,7 +48,7 @@ const CourseCard = ({params: {course}}: { params: { course: Course } }) => {
};

fetchProjects();
}, [course.course_id]);
}, [course.course_id, last_submission, projects]);



Expand Down
11 changes: 7 additions & 4 deletions frontend/app/[locale]/components/CourseControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import {useTranslation} from "react-i18next";
import {APIError, fetchUserData, UserData} from "@lib/api";

const CourseControls = ({selectedYear, onYearChange}) => {
/*
* Component containing the text and buttons displayed at the top of the home page
* @param selectedYear: currently selected year
* @param onYearChange: function that shows course cards of the selected year
* */
const currentYear = new Date().getFullYear();
const academicYear = `${currentYear - 1}-${currentYear.toString().slice(-2)}`;

Expand All @@ -33,9 +38,7 @@ const CourseControls = ({selectedYear, onYearChange}) => {
setLoading(false);
}, []);




// displayed academic year
const years = [
`${currentYear - 2}-${(currentYear - 1).toString().slice(-2)}`,
academicYear,
Expand Down Expand Up @@ -105,7 +108,7 @@ const CourseControls = ({selectedYear, onYearChange}) => {
height={'fit-content'}
gap={2}
>
{user?.role !== 3 ? (
{user?.role !== 3 ? ( // Students may not see the add course button.
<Button
variant="contained"
color="secondary"
Expand Down
4 changes: 4 additions & 0 deletions frontend/app/[locale]/components/CourseDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ interface CourseDetailsProps {
}

export default function CourseDetails({course_id}: CourseDetailsProps) {
/*
* Component used in course details page that shows the information of the course(not the title, this is displayed in the courseBanner).
* @param course_id: id of the course
* */
const [user, setUser] = useState<UserData | null>(null);
const [course, setCourse] = useState<Course | null>(null);
const [error, setError] = useState<APIError | null>(null);
Expand Down
11 changes: 7 additions & 4 deletions frontend/app/[locale]/components/CoursesGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import React, {useEffect, useState} from 'react';
import {APIError, Course, getCoursesForUser} from '@lib/api';
import { Grid, Skeleton } from '@mui/material';
import CourseCard from '@app/[locale]/components/CourseCard';
import {useTranslation} from "react-i18next";

const CoursesGrid = ({selectedYear}) => {
/*
* Grid component that displays the course cards on the home page
* @param selectedYear: currently selected year
* */
const [courses, setCourses] = useState<Course[]>([]);
const [filteredCourses, setFilteredCourses] = useState<Course[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<APIError | null>(null);

const {t} = useTranslation()

const loadingArray = [1, 2, 3, 4, 5, 6];

useEffect(() => {
Expand All @@ -21,13 +22,15 @@ const CoursesGrid = ({selectedYear}) => {
setCourses(await getCoursesForUser());
} catch (error) {
if (error instanceof APIError) setError(error);
} finally {
setLoading(false);
}
};

fetchCourses();
setLoading(false);
}, []);

// filter courses by selected year
useEffect(() => {
const [startYear, endYearSuffix] = selectedYear.split('-');
const startYearNumber = parseInt(startYear, 10);
Expand Down
8 changes: 8 additions & 0 deletions frontend/app/[locale]/components/CreateCourseForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {visuallyHidden} from "@mui/utils";
import dayjs from "dayjs";

const CreateCourseForm = () => {
/*
* Form component for creating a new course
*/
const { t } = useTranslation();
const [selectedImage, setSelectedImage] = useState<File | null>(null);
const [selectedImageURL, setSelectedImageURL] = useState<string>("");
Expand All @@ -25,6 +28,7 @@ const CreateCourseForm = () => {
const [openConfirmation, setOpenConfirmation] = useState(false); // State for confirmation dialog
const [year, setYear] = useState(0);

// Function to handle image upload
const handleImageUpload = (event: any) => {
const imageFile = event.target.files[0];
setSelectedImage(imageFile);
Expand All @@ -33,15 +37,18 @@ const CreateCourseForm = () => {
setSelectedImageURL(imageURL);
};

// Function to handle form submission
const handleSubmit = async (event: any) => {
event.preventDefault();
setOpenConfirmation(true); // Open confirmation dialog
};

// Function to close confirmation dialog
const handleConfirmationClose = () => {
setOpenConfirmation(false);
};

// Function to accept confirmation dialog
const handleConfirmationYes = async () => {
setOpenConfirmation(false);
const formData = new FormData();
Expand All @@ -62,6 +69,7 @@ const CreateCourseForm = () => {
if (selectedImage) fileReader.readAsArrayBuffer(selectedImage);
};

// Load banner image
useEffect(() => {
if (selectedImage === null) {
fetch(banner.src)
Expand Down
4 changes: 4 additions & 0 deletions frontend/app/[locale]/components/EditCourseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ interface EditCourseButtonProps{
}

const EditCourseButton = ({course_id}: EditCourseButtonProps) => {
/*
* Button that redirects to the edit course page
* @param course_id: id of the course
*/
const {t} = useTranslation();

return (
Expand Down
9 changes: 8 additions & 1 deletion frontend/app/[locale]/components/EditCourseForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,25 @@ interface EditCourseFormProps {
}

const EditCourseForm = ({courseId}: EditCourseFormProps) => {
/*
* Form used to edit a course
* @param courseId: id of the course
*/
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [open, setOpen] = useState(false);
const [year, setYear] = useState(0);
const {t} = useTranslation();
const [selectedImage, setSelectedImage] = useState<File | null>(null);
const [selectedImageURL, setSelectedImageURL] = useState<string>("");
const [loading, setLoading] = useState(true);
const [openConfirmation, setOpenConfirmation] = useState(false); // State for confirmation dialog
const {t} = useTranslation();


useEffect(() => {
const fetchCourseData = async () => {
try {
// Fetch course data + setting the states with the fetched data
const course = await getCourse(courseId);
setName(course.name);
setDescription(course.description);
Expand Down Expand Up @@ -62,10 +67,12 @@ const EditCourseForm = ({courseId}: EditCourseFormProps) => {
setOpenConfirmation(true); // Open confirmation dialog
};

// Close confirmation dialog
const handleConfirmationClose = () => {
setOpenConfirmation(false);
};

// Handle confirmation dialog yes button
const handleConfirmationYes = async () => {
setOpenConfirmation(false);
const formData = new FormData();
Expand Down
Loading
Loading