/* Instructor can view student if he is a course admin or if student is member of one of accessible for instructor group */ public async Task <bool> CanInstructorViewStudentAsync(string instructorId, string studentId) { if (await courseRolesRepo.HasUserAccessTo_Any_Course(instructorId, CourseRoleType.CourseAdmin).ConfigureAwait(false)) { return(true); } var coursesIds = (await courseManager.GetCoursesAsync()).Select(c => c.Id).ToList(); var groups = await GetAvailableForUserGroupsAsync(coursesIds, instructorId, false, actual : true, archived : false).ConfigureAwait(false); var members = await groupMembersRepo.GetGroupsMembersAsync(groups.Select(g => g.Id).ToList()).ConfigureAwait(false); return(members.Select(m => m.UserId).Contains(studentId)); }
private async Task <GroupsListResponse> GetGroupsListResponseAsync(GroupsListParameters parameters) { var groups = await groupAccessesRepo.GetAvailableForUserGroupsAsync(parameters.CourseId, UserId, false, !parameters.Archived, parameters.Archived).ConfigureAwait(false); /* Order groups by (name, createTime) and get one page of data (offset...offset+count) */ var groupIds = groups.OrderBy(g => g.Name, StringComparer.InvariantCultureIgnoreCase).ThenBy(g => g.Id) .Skip(parameters.Offset) .Take(parameters.Count) .Select(g => g.Id) .ToImmutableHashSet(); var filteredGroups = groups.Where(g => groupIds.Contains(g.Id)).ToList(); var groupMembers = await groupMembersRepo.GetGroupsMembersAsync(groupIds).ConfigureAwait(false); var membersCountByGroup = groupMembers.GroupBy(m => m.GroupId).ToDictionary(g => g.Key, g => g.Count()).ToDefaultDictionary(); var groupAccessesByGroup = await groupAccessesRepo.GetGroupAccessesAsync(groupIds).ConfigureAwait(false); var groupInfos = filteredGroups.Select(g => BuildGroupInfo( g, membersCountByGroup[g.Id], groupAccessesByGroup[g.Id], addGroupApiUrl: true )).ToList(); return(new GroupsListResponse { Groups = groupInfos, Pagination = new PaginationResponse { Offset = parameters.Offset, Count = filteredGroups.Count, TotalCount = groups.Count, } }); }
public async Task <ActionResult <CodeReviewInstructorsStatisticsResponse> > InstructorsStatistics([FromQuery(Name = "course_id")][BindRequired] string courseId, int count = 10000, DateTime?from = null, DateTime?to = null) { var course = await courseManager.FindCourseAsync(courseId); if (course == null) { return(NotFound()); } if (!from.HasValue) { from = DateTime.MinValue; } if (!to.HasValue) { to = DateTime.MaxValue; } count = Math.Min(count, 10000); var instructorIds = await courseRolesRepo.GetListOfUsersWithCourseRole(CourseRoleType.Instructor, course.Id, false).ConfigureAwait(false); var instructors = await usersRepo.GetUsersByIds(instructorIds).ConfigureAwait(false); var exerciseSlides = course.GetSlides(true).OfType <ExerciseSlide>().ToList(); var allSlideCheckings = (await slideCheckingsRepo.GetManualCheckingQueue <ManualExerciseChecking>(new ManualCheckingQueueFilterOptions { CourseId = course.Id, Count = count, OnlyChecked = null, From = @from.Value, To = to.Value, }).ConfigureAwait(false)).ToList(); var result = new CodeReviewInstructorsStatisticsResponse { AnalyzedCodeReviewsCount = allSlideCheckings.Count, Instructors = new List <CodeReviewInstructorStatistics>() }; foreach (var instructor in instructors) { var checkingsCheckedByInstructor = allSlideCheckings.Where(c => c.IsChecked && (c.LockedById == instructor.Id || c.Reviews.Any(r => r.AuthorId == instructor.Id))).ToList(); var instructorGroups = await groupsRepo.GetMyGroupsFilterAccessibleToUserAsync(course.Id, instructor.Id).ConfigureAwait(false); var instructorGroupMemberIds = (await groupMembersRepo.GetGroupsMembersAsync(instructorGroups.Select(g => g.Id).ToList()).ConfigureAwait(false)).Select(m => m.UserId); var checkingQueue = allSlideCheckings.Where(c => !c.IsChecked && instructorGroupMemberIds.Contains(c.UserId)).ToList(); var comments = checkingsCheckedByInstructor.SelectMany(c => c.NotDeletedReviews).ToList(); var instructorStatistics = new CodeReviewInstructorStatistics { Instructor = BuildShortUserInfo(instructor, discloseLogin: true), Exercises = exerciseSlides.Select( slide => new CodeReviewExerciseStatistics { SlideId = slide.Id, ReviewedSubmissionsCount = checkingsCheckedByInstructor.Where(c => c.SlideId == slide.Id).DistinctBy(c => c.SubmissionId).Count(), QueueSize = checkingQueue.Count(c => c.SlideId == slide.Id), CommentsCount = comments.Count(c => c.ExerciseChecking.SlideId == slide.Id), } ) .Where(s => s.ReviewedSubmissionsCount + s.QueueSize + s.CommentsCount > 0) // Ignore empty (zeros) records .ToList() }; result.Instructors.Add(instructorStatistics); } return(result); }