From 4e1e0d1488a91668ffff970bdb39a3c6c8d6e80f Mon Sep 17 00:00:00 2001 From: Vladislav Kopnin Date: Mon, 28 Sep 2026 17:22:09 +0300 Subject: [PATCH] Admin group: fix script loading (extra div), total submissions counter, label cleanup --- .../ru/ysu/lms/progress/SubmissionController.kt | 7 +++++++ .../ru/ysu/lms/progress/SubmissionService.kt | 4 ++++ .../lms/progress/repo/SubmissionRepository.kt | 2 ++ .../ysu/lms/web/admin/AdminGroupController.kt | 7 +++---- .../ru/ysu/lms/web/api/ApiClientProgress.kt | 17 +++++++++++++++++ .../main/resources/templates/admin/group.html | 5 ++--- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionController.kt b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionController.kt index 698a278..9652154 100644 --- a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionController.kt +++ b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionController.kt @@ -56,6 +56,13 @@ class SubmissionController( @RequestParam labId: UUID, ): List = submissions.latestPerStudent(labId) + /** Общее число решений (всех попыток) по лабораторной. */ + @GetMapping("/submissions/count") + @PreAuthorize("hasAuthority('ROLE_ADMIN')") + fun submissionCount( + @RequestParam labId: UUID, + ): Map = mapOf("count" to submissions.countForLab(labId)) + @GetMapping("/submissions/{id}/download") @PreAuthorize("hasAuthority('ROLE_ADMIN')") fun downloadForAdmin( diff --git a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionService.kt b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionService.kt index 4bff03e..1b0c869 100644 --- a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionService.kt +++ b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/SubmissionService.kt @@ -101,6 +101,10 @@ class SubmissionService( return zip to name } + /** Общее число решений (всех попыток) по лабораторной. */ + @Transactional(readOnly = true) + fun countForLab(labId: UUID): Long = submissions.countByLabId(labId) + @Transactional(readOnly = true) fun latestPerStudent(labId: UUID): List { val perStudent = mutableMapOf() diff --git a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/repo/SubmissionRepository.kt b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/repo/SubmissionRepository.kt index 23941fa..8fac751 100644 --- a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/repo/SubmissionRepository.kt +++ b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/repo/SubmissionRepository.kt @@ -14,6 +14,8 @@ interface SubmissionRepository : JpaRepository { fun findByLabIdOrderByCreatedAtDesc(labId: UUID): List + fun countByLabId(labId: UUID): Long + fun findFirstByStudentIdAndLabIdOrderBySeqDesc( studentId: UUID, labId: UUID, diff --git a/web/src/main/kotlin/ru/ysu/lms/web/admin/AdminGroupController.kt b/web/src/main/kotlin/ru/ysu/lms/web/admin/AdminGroupController.kt index e40f68e..1f5f1e0 100644 --- a/web/src/main/kotlin/ru/ysu/lms/web/admin/AdminGroupController.kt +++ b/web/src/main/kotlin/ru/ysu/lms/web/admin/AdminGroupController.kt @@ -22,7 +22,6 @@ import ru.ysu.lms.web.api.GradeSetPayload import ru.ysu.lms.web.api.GroupDetailDto import ru.ysu.lms.web.api.LabSummaryDto import ru.ysu.lms.web.api.StudentCandidateDto -import ru.ysu.lms.web.api.SubmissionDto import ru.ysu.lms.web.api.createGroup import ru.ysu.lms.web.api.downloadSubmissionAsAdmin import ru.ysu.lms.web.api.getLabAssignments @@ -38,6 +37,7 @@ import ru.ysu.lms.web.api.listGroups import ru.ysu.lms.web.api.listLabs import ru.ysu.lms.web.api.publishGrades import ru.ysu.lms.web.api.setGrade +import ru.ysu.lms.web.api.submissionCount import ru.ysu.lms.web.api.suggestComments import tools.jackson.databind.ObjectMapper import java.net.URLEncoder @@ -192,7 +192,7 @@ class AdminGroupController( ) } - fillGroupModel(model, groupViewModel(t, id, GroupRenderData(group, labs, rows, publishedLabs, submissionsBy))) + fillGroupModel(model, groupViewModel(t, id, GroupRenderData(group, labs, rows, publishedLabs))) return "admin/group" } @@ -206,7 +206,6 @@ class AdminGroupController( val labs: List, val rows: List, val publishedLabs: Set, - val submissionsBy: Map>, ) private fun groupViewModel( @@ -214,7 +213,7 @@ class AdminGroupController( id: String, data: GroupRenderData, ): GroupViewModel { - val submissionCounts = data.labs.associate { it.id to (data.submissionsBy[it]?.size ?: 0) } + val submissionCounts = data.labs.associate { it.id to api.submissionCount(token, it.id) } val candidates = runCatching { api.groupCandidates(token, id) }.getOrDefault(emptyList()) return GroupViewModel(data.group, data.labs, candidates, data.rows, data.publishedLabs, submissionCounts) } diff --git a/web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt b/web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt index ec736c4..7af70fc 100644 --- a/web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt +++ b/web/src/main/kotlin/ru/ysu/lms/web/api/ApiClientProgress.kt @@ -6,6 +6,23 @@ import org.springframework.http.HttpHeaders import org.springframework.http.MediaType import org.springframework.util.LinkedMultiValueMap +fun ApiClient.submissionCount( + token: String, + labId: String, +): Int { + val type = object : ParameterizedTypeReference>() {} + val result = + call { + client + .get() + .uri("/api/v1/submissions/count?labId={id}", labId) + .header(HttpHeaders.AUTHORIZATION, bearer(token)) + .retrieve() + .body(type) + } + return (result["count"] ?: 0L).toInt() +} + fun ApiClient.distribute( token: String, payload: DistributeRequestPayload, diff --git a/web/src/main/resources/templates/admin/group.html b/web/src/main/resources/templates/admin/group.html index 01e8bc2..09ff166 100644 --- a/web/src/main/resources/templates/admin/group.html +++ b/web/src/main/resources/templates/admin/group.html @@ -12,7 +12,7 @@
Скачать пароли - +
@@ -225,7 +225,6 @@ - @@ -234,7 +233,7 @@