diff --git a/frontend/src/i18n/en/translation.json b/frontend/src/i18n/en/translation.json index ec30e553..c2085d0c 100644 --- a/frontend/src/i18n/en/translation.json +++ b/frontend/src/i18n/en/translation.json @@ -295,6 +295,8 @@ "searchMember": "Search member", "inviteLink": "Invite link", "inviteLinkInfo": "With this link, students can join your course", + "copyLink": "Copy invite link", + "copyLinkSuccess": "Link copied to clipboard", "deleteCourse": "Delete course", "deleteCourseDescription": "Are you sure you want to delete this course? All projects and submissions will be deleted as well. This action cannot be undone.", "confirmDelete": "Confirm deletion", diff --git a/frontend/src/i18n/nl/translation.json b/frontend/src/i18n/nl/translation.json index 8bd0c05b..0a28e83a 100644 --- a/frontend/src/i18n/nl/translation.json +++ b/frontend/src/i18n/nl/translation.json @@ -299,6 +299,8 @@ "searchMember": "Zoek lid", "inviteLink": "Uitnodigingslink", "inviteLinkInfo": "Met deze link kunnen studenten zich inschrijven voor dit vak.", + "copyLink": "Kopieer uitnodiginslink", + "copyLinkSuccess": "Link gekopieerd", "deleteCourse": "Vak verwijderen", "deleteCourseDescription": "Bent u zeker dat u dit vak wilt verwijderen? Alle projecten en indieningen zullen ook verwijderd worden. Deze actie kan niet ongedaan gemaakt worden.", "confirmDelete": "Bevestig verwijdering", diff --git a/frontend/src/pages/course/components/informationTab/InformationTab.tsx b/frontend/src/pages/course/components/informationTab/InformationTab.tsx index c4103355..0cbd4495 100644 --- a/frontend/src/pages/course/components/informationTab/InformationTab.tsx +++ b/frontend/src/pages/course/components/informationTab/InformationTab.tsx @@ -1,4 +1,5 @@ import { Card, Col, Row, Space, Tooltip, Typography, theme } from "antd" +import { EditOutlined, CheckOutlined, CopyOutlined } from "@ant-design/icons" import useCourse from "../../../../hooks/useCourse" import MarkdownTextfield from "../../../../components/input/MarkdownTextfield" import { InfoCircleOutlined } from "@ant-design/icons" @@ -75,8 +76,12 @@ const InformationTab = () => { {t("course.inviteLink")}:
- , ], + }} editable={{ + icon: , onStart: () => openInviteModal({course, modal, onChange: setCourse, title: t("course.invitePeopleToCourse")}), }} style={{color:token.colorLink, cursor:"default"}} diff --git a/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx b/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx index 4b92e977..ec4a050e 100644 --- a/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx +++ b/frontend/src/pages/course/components/tabExtraBtn/InviteModalContent.tsx @@ -1,19 +1,21 @@ -import { Button, Input, Modal, Space, Switch, Tooltip, Typography } from "antd" +import { Button, Input, Modal, Space, Switch, Tooltip, Typography, theme, message } from "antd" import { FC, useMemo, useState } from "react" import { generateLink } from "../informationTab/InformationTab" import { CourseType } from "../../Course" import { HookAPI } from "antd/es/modal/useModal" -import { InfoCircleOutlined, RedoOutlined } from "@ant-design/icons" +import { InfoCircleOutlined, RedoOutlined, CopyOutlined, CheckOutlined } from "@ant-design/icons" import { useTranslation } from "react-i18next" import useApi from "../../../../hooks/useApi" import { ApiRoutes } from "../../../../@types/requests.d" const InviteModalContent: FC<{ defaultCourse: CourseType; onChange: (course: CourseType) => void }> = ({ defaultCourse, onChange }) => { const { t } = useTranslation() + const { token } = theme.useToken() const [course, setCourse] = useState(defaultCourse) const API = useApi() const [loading, setLoading] = useState(false) const url = useMemo(() => generateLink(course.courseId.toString(), course.joinKey), [course]) + const [copied, setCopied] = useState(false) const regenerateKey = async () => { setLoading(true) @@ -47,13 +49,21 @@ const InviteModalContent: FC<{ defaultCourse: CourseType; onChange: (course: Cou > - - + + {copied ? ( + + ) : ( + { + navigator.clipboard.writeText(url); + setCopied(true); + setTimeout(() => setCopied(false), 3000); // Reset after 3 seconds + }} /> + )} + } /> {course.joinKey && (