Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 48ed4a7

Browse files
authoredMay 5, 2024
added clipboard to copy the join code and redirecting to course when … (#325)
* added clipboard to copy the join code and redirecting to course when user already in course * styling
1 parent fa6987d commit 48ed4a7

File tree

3 files changed

+72
-50
lines changed

3 files changed

+72
-50
lines changed
 

‎frontend/src/components/Courses/CourseDetailTeacher.tsx

+61-47
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Menu,
1515
MenuItem,
1616
Paper,
17+
Tooltip,
1718
Typography,
1819
} from "@mui/material";
1920
import { ChangeEvent, useCallback, useEffect, useState } from "react";
@@ -24,7 +25,6 @@ import {
2425
getIdFromLink,
2526
getNearestFutureDate,
2627
getUser,
27-
appHost,
2828
ProjectDetail,
2929
} from "./CourseUtils";
3030
import {
@@ -39,6 +39,7 @@ import { timeDifference } from "../../utils/date-utils";
3939
import { authenticatedFetch } from "../../utils/authenticated-fetch";
4040
import i18next from "i18next";
4141
import { Me } from "../../types/me";
42+
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
4243

4344
interface UserUid {
4445
uid: string;
@@ -179,9 +180,17 @@ export function CourseDetailTeacher(): JSX.Element {
179180
return (
180181
<>
181182
<Title title={course.name}></Title>
182-
<Grid container direction={"row"} spacing={2} margin="1rem">
183-
<Grid item xs={5}>
184-
<Paper style={{ height: "90%", maxHeight: "90vh" }}>
183+
<Grid
184+
container
185+
direction={"row"}
186+
spacing={2}
187+
margin="1rem"
188+
style={{ height: "80vh" }}
189+
>
190+
<Grid item xs={5} height="100%">
191+
<Paper
192+
style={{ height: "100%", maxHeight: "100%", overflow: "auto" }}
193+
>
185194
<div style={{ padding: "1rem" }}>
186195
<Typography variant="h5">{t("projects")}:</Typography>
187196
<EmptyOrNotProjects projects={projects} />
@@ -191,19 +200,12 @@ export function CourseDetailTeacher(): JSX.Element {
191200
<Button>{t("newProject")}</Button>
192201
</Link>
193202
</Grid>
194-
<Grid item xs={6}>
195-
<Grid
196-
container
197-
direction={"column"}
198-
spacing={2}
199-
style={{
200-
height: "100%",
201-
}}
202-
>
203+
<Grid item xs={5} height="100%">
204+
<Grid container direction={"column"} spacing={2} height={"100%"}>
203205
<Grid
204206
item
205207
style={{
206-
height: "45.9%",
208+
height: "50%",
207209
}}
208210
>
209211
<Paper
@@ -239,7 +241,7 @@ export function CourseDetailTeacher(): JSX.Element {
239241
<Grid
240242
item
241243
style={{
242-
height: "45.9%",
244+
height: "50%",
243245
}}
244246
>
245247
<Paper
@@ -255,22 +257,6 @@ export function CourseDetailTeacher(): JSX.Element {
255257
handleCheckboxChange={handleCheckboxChange}
256258
/>
257259
</Paper>
258-
259-
<IconButton
260-
style={{ position: "absolute", bottom: 0, left: 0 }}
261-
onClick={() =>
262-
handleDeleteStudent(
263-
navigate,
264-
course.course_id,
265-
selectedStudents
266-
)
267-
}
268-
>
269-
<ClearIcon />
270-
<Typography variant="body1">{t("deleteSelected")}</Typography>
271-
</IconButton>
272-
</Grid>
273-
<Grid item>
274260
<Grid container>
275261
<Grid item>
276262
<Button onClick={handleClickCodes}>{t("joinCodes")}</Button>
@@ -291,6 +277,20 @@ export function CourseDetailTeacher(): JSX.Element {
291277
</Button>
292278
</Grid>
293279
</Grid>
280+
281+
<IconButton
282+
style={{ position: "absolute", bottom: 0, left: 0 }}
283+
onClick={() =>
284+
handleDeleteStudent(
285+
navigate,
286+
course.course_id,
287+
selectedStudents
288+
)
289+
}
290+
>
291+
<ClearIcon />
292+
<Typography variant="body1">{t("deleteSelected")}</Typography>
293+
</IconButton>
294294
</Grid>
295295
</Grid>
296296
</Grid>
@@ -486,7 +486,10 @@ function JoinCodeMenu({
486486
};
487487

488488
const handleCopyToClipboard = (join_code: string) => {
489-
navigator.clipboard.writeText(`${appHost}/join-course?code=${join_code}`);
489+
const host = window.location.host;
490+
navigator.clipboard.writeText(
491+
`${host}/${i18next.language}/courses/join?code=${join_code}`
492+
);
490493
};
491494

492495
const getCodes = useCallback(() => {
@@ -560,6 +563,9 @@ function JoinCodeMenu({
560563
vertical: "bottom",
561564
horizontal: "center",
562565
}}
566+
style={{
567+
width: "25vw",
568+
}}
563569
>
564570
<MenuItem disabled>
565571
<Typography variant="h6">{t("joinCodes")}</Typography>
@@ -568,25 +574,33 @@ function JoinCodeMenu({
568574
elevation={0}
569575
style={{
570576
margin: "1rem",
577+
width: "100%",
578+
maxHeight: "20vh",
579+
height: "20vh",
580+
overflowY: "auto",
571581
}}
572582
>
573583
{codes.map((code: JoinCode) => (
574-
<MenuItem
575-
onClick={() => handleCopyToClipboard(code.join_code)}
576-
key={code.join_code}
577-
>
584+
<MenuItem style={{ width: "100%" }} key={code.join_code}>
578585
<Grid container direction={"row"}>
579-
<Grid marginRight={"1rem"} item>
580-
<Typography variant="body1">
581-
{code.expiry_time
582-
? timeDifference(code.expiry_time)
583-
: t("noExpiryDate")}
584-
</Typography>
585-
</Grid>
586-
<Grid item>
587-
<Typography variant="body1">
588-
{code.for_admins ? t("forAdmins") : t("forStudents")}
589-
</Typography>
586+
<Grid item flexGrow={1}>
587+
<Box display="flex" gap="1rem">
588+
<Typography variant="body1">
589+
{code.expiry_time
590+
? timeDifference(code.expiry_time)
591+
: t("noExpiryDate")}
592+
</Typography>
593+
<Typography variant="body1">
594+
{code.for_admins ? t("forAdmins") : t("forStudents")}
595+
</Typography>
596+
<Tooltip title={t("copyToClipboard")}>
597+
<IconButton
598+
onClick={() => handleCopyToClipboard(code.join_code)}
599+
>
600+
<ContentCopyIcon />
601+
</IconButton>
602+
</Tooltip>
603+
</Box>
590604
</Grid>
591605
<Grid item>
592606
<IconButton onClick={() => handleDeleteCode(code.join_code)}>

‎frontend/src/components/Courses/CourseUtils.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ interface Deadline {
2727
}
2828

2929
export const apiHost = import.meta.env.VITE_APP_API_HOST;
30-
export const appHost = import.meta.env.VITE_APP_HOST;
3130
/**
3231
* @returns The uid of the acces token of the logged in user
3332
*/

‎frontend/src/loaders/join-code.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ export async function synchronizeJoinCode() {
1313
const joinCode = queryParams.get("code");
1414

1515
if (joinCode) {
16-
const response = await authenticatedFetch(new URL("/courses/join", API_URL));
16+
const response = await authenticatedFetch(
17+
new URL("/courses/join", API_URL),
18+
{
19+
method: "POST",
20+
body: JSON.stringify({ join_code: joinCode }),
21+
headers: { "Content-Type": "application/json" },
22+
}
23+
);
1724

18-
if (response.ok) {
25+
if (response.ok || response.status === 409) {
1926
const responseData = await response.json();
2027
return redirect(
2128
`/${i18next.language}/courses/${responseData.data.course_id}`
2229
);
30+
} else {
31+
throw new Error("Invalid join code");
2332
}
2433
} else {
2534
throw new Error("No join code provided");

0 commit comments

Comments
 (0)