From 59de3bb2e5d2d3b5dc942dcd7436e748ff3cc315 Mon Sep 17 00:00:00 2001 From: ivan-pelly Date: Wed, 8 Apr 2026 07:56:04 -0700 Subject: [PATCH] Updates to see others' students --- api/src/Controllers/StudentController.cs | 4 +- .../Models/DatabaseObjects/dbUserStudent.cs | 1 + .../Repositories/StudentRepository.cs | 32 +++++-- .../Models/ResponseTypes/StudentResponse.cs | 2 + api/src/Services/PermissionMatrix.cs | 22 ++--- .../sp_Student_GetWithAssignments.sql | 36 +++++--- .../student-card-list/student-card-list.html | 15 +++- .../student-card-list/student-card-list.scss | 43 ++++++++++ .../student-card-list/student-card-list.ts | 16 +++- .../src/app/desktop/pages/home/home.ts | 83 +++++++++++++++---- .../app/mobile/pages/students/students.html | 10 +++ .../app/mobile/pages/students/students.scss | 43 ++++++++++ .../src/app/mobile/pages/students/students.ts | 14 +++- .../app/shared/classes/student-card.dto.ts | 2 + .../app/shared/services/student.service.ts | 8 +- 15 files changed, 278 insertions(+), 53 deletions(-) diff --git a/api/src/Controllers/StudentController.cs b/api/src/Controllers/StudentController.cs index bf9b64e..d6a744e 100644 --- a/api/src/Controllers/StudentController.cs +++ b/api/src/Controllers/StudentController.cs @@ -17,7 +17,7 @@ public class StudentController : BaseController [HttpGet("my")] [Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")] [ProducesResponseType(typeof(ResponseResult>), StatusCodes.Status200OK)] - public async Task>>> GetMyStudents() + public async Task>>> GetMyStudents([FromQuery] string? scope = null) { var (userId, email, programId, role, error) = GetProgramUserFromClaims(); @@ -26,7 +26,7 @@ public class StudentController : BaseController return error; } - var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role); + var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role, scope); return Ok(new ResponseResult> { diff --git a/api/src/DataAccess/Models/DatabaseObjects/dbUserStudent.cs b/api/src/DataAccess/Models/DatabaseObjects/dbUserStudent.cs index a3b325e..e47dee0 100644 --- a/api/src/DataAccess/Models/DatabaseObjects/dbUserStudent.cs +++ b/api/src/DataAccess/Models/DatabaseObjects/dbUserStudent.cs @@ -6,4 +6,5 @@ public class dbUserStudent public Guid? IdUser { get; set; } public Guid? IdStudent { get; set; } public bool? IsPrimary { get; set; } + public string? OwnerName { get; set; } } diff --git a/api/src/DataAccess/Repositories/StudentRepository.cs b/api/src/DataAccess/Repositories/StudentRepository.cs index fcb8469..5d970c9 100644 --- a/api/src/DataAccess/Repositories/StudentRepository.cs +++ b/api/src/DataAccess/Repositories/StudentRepository.cs @@ -10,22 +10,38 @@ public class StudentRepository { private IDbConnection Connection => new MySqlConnection(DatabaseManager.ConnectionString); - public async Task> GetMyStudentsAsync(Guid userId, Guid programId, string role) + // ***************************************************************** + // Returns students visible to the current user. When scope is + // "all", returns every student in the program enriched with the + // owning user's name. Otherwise returns only the user's own. + // ***************************************************************** + public async Task> GetMyStudentsAsync(Guid userId, Guid programId, string role, string? scope = null) { using var db = Connection; using var multi = await db.QueryMultipleAsync( "sp_Student_GetWithAssignments", - new { p_id_program = programId.ToString(), p_id_user = userId.ToString() }, + new { p_id_program = programId.ToString(), p_id_user = userId.ToString(), p_scope = scope }, commandType: CommandType.StoredProcedure); - var students = await multi.ReadAsync(); - var assignments = await multi.ReadAsync(); + var students = (await multi.ReadAsync()).ToList(); + var assignments = (await multi.ReadAsync()).ToList(); - var myStudents = students.Where(s => - PermissionService.IsAllowed(role, EntityType.Student, PermissionAction.Read, assignments.Any(a => a.IdStudent == s.StudentId && a.IdUser == userId)) - ); + // When scope is "all", return every student in the program. + // Otherwise, return only students assigned to the current user. + var filtered = scope == "all" + ? students + : students.Where(s => assignments.Any(a => a.IdStudent == s.StudentId && a.IdUser == userId)).ToList(); - return myStudents; + // Enrich each student with the primary owner's display name and ownership flag. + foreach (var student in filtered) + { + var owner = assignments.FirstOrDefault(a => a.IdStudent == student.StudentId && (a.IsPrimary == true)); + owner ??= assignments.FirstOrDefault(a => a.IdStudent == student.StudentId); + student.OwnerName = owner?.OwnerName; + student.IsMine = assignments.Any(a => a.IdStudent == student.StudentId && a.IdUser == userId); + } + + return filtered; } public async Task GetByIdAsync(Guid idStudent) diff --git a/api/src/Models/ResponseTypes/StudentResponse.cs b/api/src/Models/ResponseTypes/StudentResponse.cs index 19ba26f..7722cd5 100644 --- a/api/src/Models/ResponseTypes/StudentResponse.cs +++ b/api/src/Models/ResponseTypes/StudentResponse.cs @@ -10,4 +10,6 @@ public class StudentResponse public int GoalCount { get; set; } public int ProgressEventCount { get; set; } public int BenchmarkCount { get; set; } + public string? OwnerName { get; set; } + public bool IsMine { get; set; } } diff --git a/api/src/Services/PermissionMatrix.cs b/api/src/Services/PermissionMatrix.cs index 4ddf0de..b737a5d 100644 --- a/api/src/Services/PermissionMatrix.cs +++ b/api/src/Services/PermissionMatrix.cs @@ -210,29 +210,29 @@ public static class PermissionMatrix [EntityType.Student] = new() { [PermissionAction.Create] = MineOnly, - [PermissionAction.Read] = MineOnly, - [PermissionAction.Update] = MineOnly, + [PermissionAction.Read] = Allow, + [PermissionAction.Update] = Allow, [PermissionAction.Delete] = MineOnly, }, [EntityType.Goal] = new() { - [PermissionAction.Create] = MineOnly, - [PermissionAction.Read] = MineOnly, - [PermissionAction.Update] = MineOnly, + [PermissionAction.Create] = Allow, + [PermissionAction.Read] = Allow, + [PermissionAction.Update] = Allow, [PermissionAction.Delete] = MineOnly, }, [EntityType.ProgressEvent] = new() { - [PermissionAction.Create] = MineOnly, - [PermissionAction.Read] = MineOnly, - [PermissionAction.Update] = MineOnly, + [PermissionAction.Create] = Allow, + [PermissionAction.Read] = Allow, + [PermissionAction.Update] = Allow, [PermissionAction.Delete] = MineOnly, }, [EntityType.Benchmark] = new() { - [PermissionAction.Create] = MineOnly, - [PermissionAction.Read] = MineOnly, - [PermissionAction.Update] = MineOnly, + [PermissionAction.Create] = Allow, + [PermissionAction.Read] = Allow, + [PermissionAction.Update] = Allow, [PermissionAction.Delete] = MineOnly, }, }, diff --git a/db/Objects/procedures/sp_Student_GetWithAssignments.sql b/db/Objects/procedures/sp_Student_GetWithAssignments.sql index 9d0f211..33d4d8d 100644 --- a/db/Objects/procedures/sp_Student_GetWithAssignments.sql +++ b/db/Objects/procedures/sp_Student_GetWithAssignments.sql @@ -1,7 +1,8 @@ DELIMITER ;; CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_GetWithAssignments`( IN p_id_program CHAR(36), - IN p_id_user CHAR(36) + IN p_id_user CHAR(36), + IN p_scope VARCHAR(10) ) BEGIN SELECT @@ -17,14 +18,29 @@ BEGIN INNER JOIN student s ON s.id_student = vc.studentId WHERE s.id_program = p_id_program ORDER BY vc.studentId; - SELECT - us.id_user_student, - us.id_user, - us.id_student, - us.is_primary - FROM user_student us - INNER JOIN student s ON s.id_student = us.id_student - WHERE us.id_user = p_id_user - AND s.id_program = p_id_program; + + IF p_scope = 'all' THEN + SELECT + us.id_user_student, + us.id_user, + us.id_student, + us.is_primary, + u.name AS ownerName + FROM user_student us + INNER JOIN student s ON s.id_student = us.id_student + INNER JOIN `user` u ON u.id_user = us.id_user + WHERE s.id_program = p_id_program; + ELSE + SELECT + us.id_user_student, + us.id_user, + us.id_student, + us.is_primary, + NULL AS ownerName + FROM user_student us + INNER JOIN student s ON s.id_student = us.id_student + WHERE us.id_user = p_id_user + AND s.id_program = p_id_program; + END IF; END;; DELIMITER ; diff --git a/ui/winstudentgoaltracker/src/app/desktop/components/student-card-list/student-card-list.html b/ui/winstudentgoaltracker/src/app/desktop/components/student-card-list/student-card-list.html index 58e5d4f..557eb26 100644 --- a/ui/winstudentgoaltracker/src/app/desktop/components/student-card-list/student-card-list.html +++ b/ui/winstudentgoaltracker/src/app/desktop/components/student-card-list/student-card-list.html @@ -1,6 +1,13 @@
-

My Students - {{ students().length}}

+

{{ showAll() ? 'All Students' : 'My Students' }} - {{ students().length }}

+