diff --git a/hwproj.front/package-lock.json b/hwproj.front/package-lock.json index 670634c7c..7a9ea93ac 100644 --- a/hwproj.front/package-lock.json +++ b/hwproj.front/package-lock.json @@ -9634,7 +9634,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -9731,7 +9731,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "copy-concurrently": { "version": "1.0.5", @@ -11228,7 +11228,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "ejs": { "version": "2.7.4", @@ -11299,7 +11299,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "encoding": { "version": "0.1.13", @@ -17184,7 +17184,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memfs": { "version": "3.2.2", @@ -17250,7 +17250,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-stream": { "version": "2.0.0", @@ -17265,7 +17265,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "microevent.ts": { "version": "0.1.1", @@ -19799,6 +19799,11 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "qrcode.react": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.1.0.tgz", + "integrity": "sha512-uqXVIIVD/IPgWLYxbOczCNAQw80XCM/LulYDADF+g2xDsPj5OoRwSWtIS4jGyp295wyjKstfG1qIv/I2/rNWpQ==" + }, "qs": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", @@ -22532,7 +22537,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" }, "strip-comments": { "version": "1.0.2", @@ -23430,7 +23435,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "unquote": { "version": "1.1.1", @@ -23630,12 +23635,12 @@ "utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "8.3.2", diff --git a/hwproj.front/package.json b/hwproj.front/package.json index 671b57ea9..94adce34b 100644 --- a/hwproj.front/package.json +++ b/hwproj.front/package.json @@ -35,6 +35,7 @@ "lowdb": "^1.0.0", "portable-fetch": "^3.0.0", "prop-types": "^15.7.2", + "qrcode.react": "^4.1.0", "react": "^16.12.0", "react-dom": "^16.12.0", "react-markdown": "^4.3.1", diff --git a/hwproj.front/src/components/Courses/Course.tsx b/hwproj.front/src/components/Courses/Course.tsx index 13fc5ef56..26dfda59a 100644 --- a/hwproj.front/src/components/Courses/Course.tsx +++ b/hwproj.front/src/components/Courses/Course.tsx @@ -6,19 +6,21 @@ import AddHomework from "../Homeworks/AddHomework"; import StudentStats from "./StudentStats"; import NewCourseStudents from "./NewCourseStudents"; import ApiSingleton from "../../api/ApiSingleton"; -import {Button, Grid, Tab, Tabs, Typography, IconButton, Switch, CircularProgress} from "@material-ui/core"; +import {Button, Grid, Tab, Tabs, Typography, IconButton, CircularProgress} from "@material-ui/core"; import EditIcon from "@material-ui/icons/Edit"; import {useEffect, useState} from "react"; import {makeStyles} from "@material-ui/styles"; import VisibilityOffIcon from '@material-ui/icons/VisibilityOff'; import VisibilityIcon from '@material-ui/icons/Visibility'; -import {Alert, AlertTitle, Chip, Stack} from "@mui/material"; +import {Alert, AlertTitle, Chip, Dialog, DialogContent, DialogTitle, Stack} from "@mui/material"; import CourseExperimental from "./CourseExperimental"; import {useParams, useNavigate} from 'react-router-dom'; import MentorsList from "../Common/MentorsList"; import LecturerStatistics from "./Statistics/LecturerStatistics"; import AssessmentIcon from '@mui/icons-material/Assessment'; import NameBuilder from "../Utils/NameBuilder"; +import {QRCodeSVG} from 'qrcode.react'; +import {Center} from "@skbkontur/react-ui"; type TabValue = "homeworks" | "stats" | "applications" @@ -36,6 +38,7 @@ interface ICourseState { newStudents: AccountDataDto[]; isReadingMode: boolean; studentSolutions: StatisticsCourseMatesModel[]; + showQrCode: boolean; } interface IPageState { @@ -65,6 +68,7 @@ const Course: React.FC = () => { newStudents: [], isReadingMode: true, studentSolutions: [], + showQrCode: false }) const [pageState, setPageState] = useState({ @@ -121,7 +125,7 @@ const Course: React.FC = () => { const setCurrentState = async () => { const course = await ApiSingleton.coursesApi.apiCoursesByCourseIdGet(+courseId!) - // У пользователя изменилась роль (иначе он не может стать лектором в курсе), + // У пользователя изменилась роль (иначе он не может стать лектором в курсе), // однако он все ещё использует токен с прежней ролью const shouldRefreshToken = !isMentor && @@ -174,6 +178,19 @@ const Course: React.FC = () => { if (isFound) { return (
+ setCourseState(prevState => ({...prevState, showQrCode: false}))} + > + + Поделитесь ссылкой на курс с помощью QR-кода + + +
+ +
+
+
{course.isCompleted && @@ -186,10 +203,16 @@ const Course: React.FC = () => { : !isMentor ? "Вы можете записаться на курс и отправлять решения." : ""} } - + - - {NameBuilder.getCourseFullName(course.name!, course.groupName)}   + + setCourseState(prevState => ({ + ...prevState, + showQrCode: true + }))}> + {NameBuilder.getCourseFullName(course.name!, course.groupName)} + {isLecturer && { } {isCourseMentor && isLecturer && !isReadingMode! && ( - + )} - + @@ -224,7 +247,8 @@ const Course: React.FC = () => { {isCourseMentor && isLecturer && isReadingMode && - setLecturerStatsState(true)}> + setLecturerStatsState(true)}> Статистика лекторов по курсу