Skip to content

Commit 4da30c9

Browse files
committed
CourseFilter: показывать закрепленных студентов других преподавателей
1 parent 962e345 commit 4da30c9

File tree

5 files changed

+99
-19
lines changed

5 files changed

+99
-19
lines changed

HwProj.APIGateway/HwProj.APIGateway.API/Controllers/CoursesController.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,19 @@ public async Task<CoursePreviewView[]> GetAllCourses()
4747
}
4848

4949
[HttpGet("getAllData/{courseId}")]
50-
[ProducesResponseType(typeof(CourseViewModel), (int)HttpStatusCode.OK)]
50+
[ProducesResponseType(typeof(CourseAllData), (int)HttpStatusCode.OK)]
5151
public async Task<IActionResult> GetAllCourseData(long courseId)
5252
{
5353
var courseResult = await _coursesClient.GetAllCourseData(courseId);
5454
if (!courseResult.Succeeded)
5555
return BadRequest(courseResult.Errors[0]);
5656

57-
var result = await ToCourseViewModel(courseResult.Value);
57+
var assignedStudents = await _coursesClient.GetMentorsToAssignedStudents(courseId);
58+
var result = new CourseAllData()
59+
{
60+
Course = await ToCourseViewModel(courseResult.Value),
61+
AssignedStudents = assignedStudents
62+
};
5863
return Ok(result);
5964
}
6065

HwProj.Common/HwProj.Models/CoursesService/ViewModels/CourseViewModels.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.ComponentModel.DataAnnotations;
44
using System.Linq;
55
using HwProj.Models.AuthService.DTO;
6+
using HwProj.Models.CoursesService.DTO;
67

78
namespace HwProj.Models.CoursesService.ViewModels
89
{
@@ -57,6 +58,12 @@ public class CourseViewModel
5758
public HomeworkViewModel[] Homeworks { get; set; }
5859
}
5960

61+
public class CourseAllData
62+
{
63+
public CourseViewModel Course { get; set; }
64+
public MentorToAssignedStudentsDTO[] AssignedStudents { get; set; }
65+
}
66+
6067
// Модель для списка всех курсов
6168
public class CoursePreview
6269
{

HwProj.CoursesService/HwProj.CoursesService.Client/ICoursesServiceClient.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public interface ICoursesServiceClient
1111
Task<CoursePreview[]> GetAllCourses();
1212
Task<CourseDTO?> GetCourseById(long courseId);
1313
Task<Result<CourseDTO>> GetCourseByIdForMentor(long courseId, string mentorId);
14+
/// Получить полную информацию о курсе без учетов фильтров для преподавателей
1415
Task<Result<CourseDTO>> GetAllCourseData(long courseId);
1516
Task<CourseDTO?> GetCourseByTask(long taskId);
1617
Task<Result> DeleteCourse(long courseId);

hwproj.front/src/api/api.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,25 @@ export enum CategoryState {
299299
NUMBER_2 = <any> 2,
300300
NUMBER_3 = <any> 3
301301
}
302+
/**
303+
*
304+
* @export
305+
* @interface CourseAllData
306+
*/
307+
export interface CourseAllData {
308+
/**
309+
*
310+
* @type {CourseViewModel}
311+
* @memberof CourseAllData
312+
*/
313+
course?: CourseViewModel;
314+
/**
315+
*
316+
* @type {Array<MentorToAssignedStudentsDTO>}
317+
* @memberof CourseAllData
318+
*/
319+
assignedStudents?: Array<MentorToAssignedStudentsDTO>;
320+
}
302321
/**
303322
*
304323
* @export
@@ -1470,6 +1489,25 @@ export interface LoginViewModel {
14701489
*/
14711490
rememberMe: boolean;
14721491
}
1492+
/**
1493+
*
1494+
* @export
1495+
* @interface MentorToAssignedStudentsDTO
1496+
*/
1497+
export interface MentorToAssignedStudentsDTO {
1498+
/**
1499+
*
1500+
* @type {string}
1501+
* @memberof MentorToAssignedStudentsDTO
1502+
*/
1503+
mentorId?: string;
1504+
/**
1505+
*
1506+
* @type {Array<string>}
1507+
* @memberof MentorToAssignedStudentsDTO
1508+
*/
1509+
selectedStudentsIds?: Array<string>;
1510+
}
14731511
/**
14741512
*
14751513
* @export
@@ -5172,7 +5210,7 @@ export const CoursesApiFp = function(configuration?: Configuration) {
51725210
* @param {*} [options] Override http request option.
51735211
* @throws {RequiredError}
51745212
*/
5175-
coursesGetAllCourseData(courseId: number, options?: any): (fetch?: FetchAPI, basePath?: string) => Promise<CourseViewModel> {
5213+
coursesGetAllCourseData(courseId: number, options?: any): (fetch?: FetchAPI, basePath?: string) => Promise<CourseAllData> {
51765214
const localVarFetchArgs = CoursesApiFetchParamCreator(configuration).coursesGetAllCourseData(courseId, options);
51775215
return (fetch: FetchAPI = isomorphicFetch, basePath: string = BASE_PATH) => {
51785216
return fetch(basePath + localVarFetchArgs.url, localVarFetchArgs.options).then((response) => {

hwproj.front/src/components/Courses/CourseFilter.tsx

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {FC, useEffect, useState} from 'react';
2-
import {HomeworkViewModel, AccountDataDto} from '../../api';
2+
import {HomeworkViewModel, AccountDataDto, MentorToAssignedStudentsDTO} from '../../api';
33
import Grid from "@material-ui/core/Grid";
4-
import {Autocomplete} from "@mui/material";
4+
import {Autocomplete, Chip} from "@mui/material";
55
import TextField from "@material-ui/core/TextField";
66
import ApiSingleton from "../../api/ApiSingleton";
77
import ErrorsHandler from "../Utils/ErrorsHandler";
@@ -22,6 +22,8 @@ interface ICourseFilterState {
2222
courseStudents: AccountDataDto[];
2323
selectedHomeworks: HomeworkViewModel[];
2424
selectedStudents: AccountDataDto[];
25+
mentors: AccountDataDto[];
26+
assignedStudents: MentorToAssignedStudentsDTO[]
2527
}
2628

2729
// Если преподаватель не выбрал ни одного студента, по умолчанию регистрируем всех. Аналогично с выбором домашних работ
@@ -30,7 +32,9 @@ const CourseFilter: FC<ICourseFilterProps> = (props) => {
3032
courseHomeworks: [],
3133
courseStudents: [],
3234
selectedHomeworks: [],
33-
selectedStudents: []
35+
selectedStudents: [],
36+
assignedStudents: [],
37+
mentors: []
3438
});
3539

3640
// Состояние для отображения элемента загрузки
@@ -39,35 +43,36 @@ const CourseFilter: FC<ICourseFilterProps> = (props) => {
3943
// Состояние для отображения поля выбора студентов
4044
const [isStudentsSelectionHidden, setIsStudentsSelectionHidden] = useState<boolean>(props.isStudentsSelectionHidden);
4145

42-
// Если у преподавателя в workspace все студенты, отображаем "Все" в компоненте, значений при этом не выбрано.
43-
// Функция, необходимые для корректного отображения выбранных элементов.
44-
function getItemsView<T>(selected: T[], all: T[]): T[] {
45-
return selected.length === all.length ? [] : selected;
46-
}
47-
4846
useEffect(() => {
4947
const fetchCourseDataForMentor = async () => {
5048
try {
51-
const courseViewModel = await ApiSingleton.coursesApi.coursesGetAllCourseData(props.courseId);
49+
const {
50+
course,
51+
assignedStudents
52+
} = await ApiSingleton.coursesApi.coursesGetAllCourseData(props.courseId);
53+
if (course === undefined || assignedStudents === undefined) return
54+
5255
const mentorWorkspace =
5356
await ApiSingleton.coursesApi.coursesGetMentorWorkspace(props.courseId, props.mentorId);
5457

5558
props.onSelectedStudentsChange(mentorWorkspace.students ?? [])
5659
props.onSelectedHomeworksChange(mentorWorkspace.homeworks ?? [])
5760

5861
// Для корректного отображения "Все" при инцициализации (получении данных с бэкенда)
59-
const allCourseStudentsCount = (courseViewModel.acceptedStudents?.length ?? 0) + (courseViewModel.newStudents?.length ?? 0);
62+
const allCourseStudentsCount = (course.acceptedStudents?.length ?? 0) + (course.newStudents?.length ?? 0);
6063
const initSelectedStudentsView = mentorWorkspace.students?.length === allCourseStudentsCount ?
6164
[] : (mentorWorkspace.students) ?? [];
62-
const initSelectedHomeworksView = mentorWorkspace.homeworks?.length === courseViewModel.homeworks?.length ?
65+
const initSelectedHomeworksView = mentorWorkspace.homeworks?.length === course.homeworks?.length ?
6366
[] : (mentorWorkspace.homeworks ?? []);
6467

6568
setState(prevState => ({
6669
...prevState,
67-
courseHomeworks: courseViewModel.homeworks ?? [],
68-
courseStudents: courseViewModel.acceptedStudents ?? [],
70+
courseHomeworks: course.homeworks ?? [],
71+
courseStudents: course.acceptedStudents ?? [],
6972
selectedStudents: initSelectedStudentsView,
7073
selectedHomeworks: initSelectedHomeworksView,
74+
mentors: course.mentors!,
75+
assignedStudents: assignedStudents.filter(x => x.mentorId !== props.mentorId)
7176
}))
7277

7378
setIsLoading(false);
@@ -94,6 +99,14 @@ const CourseFilter: FC<ICourseFilterProps> = (props) => {
9499
props.onSelectedHomeworksChange(state.selectedHomeworks)
95100
}, [state.selectedHomeworks]);
96101

102+
//TODO: memoize?
103+
const getAssignedMentors = (studentId: string) =>
104+
state.assignedStudents
105+
.filter(x => x.selectedStudentsIds!.includes(studentId))
106+
.map(x => state.mentors.find(m => m.userId === x.mentorId))
107+
.filter(x => x !== undefined)
108+
.map(x => x.name + ' ' + x.surname)
109+
97110
return (
98111
<div>
99112
{isLoading ? (
@@ -150,7 +163,11 @@ const CourseFilter: FC<ICourseFilterProps> = (props) => {
150163
multiple
151164
fullWidth
152165
options={state.courseStudents}
153-
getOptionLabel={(option: AccountDataDto) => option.surname + ' ' + option.name}
166+
getOptionLabel={(option: AccountDataDto) => {
167+
const assignedMentors = getAssignedMentors(option.userId!)
168+
const suffix = assignedMentors.length > 0 ? " (преподаватель " + assignedMentors[0] + ")" : ""
169+
return option.surname + ' ' + option.name + suffix;
170+
}}
154171
getOptionKey={(option: AccountDataDto) => option.userId ?? ""}
155172
filterSelectedOptions
156173
isOptionEqualToValue={(option, value) => option.userId === value.userId}
@@ -161,7 +178,19 @@ const CourseFilter: FC<ICourseFilterProps> = (props) => {
161178
label={state.selectedStudents.length === 0 ? "" : `Студенты (${state.selectedStudents.length})`}
162179
placeholder={state.selectedStudents.length === 0 ? "Все студенты" : ""}
163180
/>)}
164-
noOptionsText={'На курсе больше нет студентов'}
181+
renderTags={(value, getTagProps) =>
182+
value.map((option, index) => {
183+
const hasAssignedStudents = getAssignedMentors(option.userId!).length > 0
184+
return (
185+
<Chip
186+
label={option.surname + ' ' + option.name}
187+
{...getTagProps({index})}
188+
color={hasAssignedStudents ? "info" : "default"}
189+
/>
190+
);
191+
})
192+
}
193+
noOptionsText={'На курсе нет студентов'}
165194
value={state.selectedStudents}
166195
onChange={(_, values) => {
167196
setState((prevState) => ({

0 commit comments

Comments
 (0)