Skip to content
Snippets Groups Projects
Commit 82585040 authored by Ruben Backx's avatar Ruben Backx :coffee:
Browse files

Merge branch '151-warning-if-add-new-submission-when-latest-submission-counts' into 'development'

Resolve "Warning if add new submission when latest submission counts"

Closes #147 and #151

See merge request !237
parents d38be4d5 f29f680c
Branches
No related tags found
2 merge requests!260Deploy,!237Resolve "Warning if add new submission when latest submission counts"
......@@ -11,13 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- User is informed of grading and staff/students importing errors. @dsavvidi
- Previews for importing. @dsavvidi
- Warning is shown if trying to submit again for an assignment with a passing grade (@dsavvidi).
### Fixed
- Sometimes, two submissions would be created for the same submission leading to the group page not loading (@rwbackx)
- Students can now see their submissions even if the course is archived. @dsavvidi
- "No feedback" message is now correctly shown (@dsavvidi).
- Tooltip in grading dialog now readable (@dsavvidi).
- Students can now see their submissions even if the course is archived. (@dsavvidi)
## [2.2.2]
......
......@@ -41,6 +41,7 @@ import nl.tudelft.submit.dto.create.MailMessageCreateDTO;
import nl.tudelft.submit.dto.create.NotificationCreateDTO;
import nl.tudelft.submit.dto.create.grading.GradedFeedbackCreateDTO;
import nl.tudelft.submit.dto.helper.TimeFrame;
import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentDetailsDTO;
import nl.tudelft.submit.enums.GradableType;
import nl.tudelft.submit.enums.NotificationPreference;
import nl.tudelft.submit.exception.GroupSwitchingException;
......@@ -620,6 +621,22 @@ public class GradeService {
return score.getScore() >= edition.getPassingScore();
}
/**
* Gets whether a group has passed an assignment.
*
* @param assignmentId The id of the assignment
* @param groupId The id of the group
* @return True iff the group has passed
*/
public boolean hasPassedAssignment(Long assignmentId, Long groupId) {
SubmitAssignmentDetailsDTO assignment = assignmentService.getSubmitAssignmentDetails(assignmentId);
List<SubmissionDetailsDTO> submissions = submissionService
.getSubmissionsOfAssignmentForGroup(assignmentId, groupId);
return getRelevantGrade(submissions)
.map(g -> isPassing(g, assignment.getModule().getEdition().getId()))
.orElse(false);
}
/**
* Returns the display string for a score.
*
......
......@@ -203,6 +203,7 @@ assignment.import_grades.id_type.username = Username
assignment.import_grades.id_type.group_name = Group name
assignment.import_grades.grade_column = Grade column
assignment.import_grades.grade_column.help = Select the column in which the scores are stored.
assignment.passed_warning = You have a passing grade for this assignment. Submitting again will overwrite this grade!
people.import.csv.successful = Successfully imported {0} people.
grades.import.csv.successful = Successfully imported {0} grade(s).
......
......@@ -37,6 +37,15 @@
class="flex vertical p-7"
enctype="multipart/form-data">
<h1 class="underlined font-500" th:text="#{assignment.submit}"></h1>
<div
th:if="${@gradeService.hasPassedAssignment(assignment.id, group.id)}"
class="banner"
data-type="warning">
<span class="banner__icon fa-solid fa-warning"></span>
<p th:text="#{assignment.passed_warning}"></p>
</div>
<div th:id="|submit-${assignment.id}-overlay-dropbox|">
<div th:id="drop-area" th:dropzone="drop-zone" class="drop-area" data-drop>
<input th:name="group.id" th:value="${group.id}" type="hidden" />
......
......@@ -223,11 +223,12 @@
<label for="passing-grade" th:text="#{grading.passing_grade}"></label>
<div class="tooltip">
<span class="tooltip__control fa-solid fa-question"></span>
<div role="tooltip">
<div role="tooltip" style="white-space: initial; min-width: 30rem">
<p class="tooltip_text" th:text="#{grading.passing_grade.help}"></p>
</div>
</div>
</div>
<input
th:if="${objectType=='edition'}"
id="passing-grade"
......
......@@ -116,10 +116,12 @@
th:text="#{submission.staff_feedback}"></button>
</div>
<div th:id="|staff-feedback-${submission.id}|">
<div th:if="${submission.feedback.isEmpty()}">
<span th:text="#{submission.no_feedback}"></span>
</div>
<div
th:id="|staff-feedback-${submission.id}|"
th:unless="${submission.feedback.isEmpty()}">
<th:block
th:each="feedback : ${submission.feedback}"
th:if="${@authorizationService.canViewGroupFeedback(submission.group.id, feedback)}">
......@@ -150,9 +152,8 @@
<div
th:id="|script-feedback-${submission.id}|"
th:unless="${submission.scriptResults.isEmpty()}"
th:with="trainResult = ${submission.scriptResults[0]}"
th:hidden="${!submission.feedback.isEmpty()}">
th:unless="${!submission.feedback.isEmpty() || submission.scriptResults.isEmpty()}"
th:with="trainResult = ${submission.scriptResults[0]}">
<div>
<th:block th:each="wagonResult, iter : ${trainResult.subresults}">
<div class="accordion__header flex space-between pil-5 pbl-3">
......
......@@ -17,6 +17,7 @@
*/
package nl.tudelft.submit.service.grading;
import static java.time.LocalDateTime.now;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
......@@ -28,6 +29,7 @@ import static org.mockito.Mockito.when;
import java.time.LocalDateTime;
import java.util.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
......@@ -47,6 +49,7 @@ import nl.tudelft.submit.cache.EditionCacheManager;
import nl.tudelft.submit.cache.SubmissionCacheManager;
import nl.tudelft.submit.dto.create.grading.GradingFormulaCreateDTO;
import nl.tudelft.submit.dto.patch.grading.GradingFormulaPatchDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentDetailsDTO;
import nl.tudelft.submit.enums.GradableType;
import nl.tudelft.submit.exception.ScoreFormatException;
import nl.tudelft.submit.model.SubmitEdition;
......@@ -54,9 +57,7 @@ import nl.tudelft.submit.model.grading.*;
import nl.tudelft.submit.repository.SubmitEditionRepository;
import nl.tudelft.submit.repository.grading.EditionCalculatedScoreRepository;
import nl.tudelft.submit.repository.grading.ModuleGradingFormulaRepository;
import nl.tudelft.submit.service.EditionService;
import nl.tudelft.submit.service.FormulaService;
import nl.tudelft.submit.service.GradeService;
import nl.tudelft.submit.service.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
......@@ -112,15 +113,59 @@ public class GradeServiceTest {
@Autowired
private PersonControllerApi personApi;
@MockBean
private AssignmentService assignmentService;
@MockBean
private SubmissionService submissionService;
EditionCalculatedScore EDITION_GRADE_1 = EditionCalculatedScore.builder()
.id(new CalculatedScore.Id(EDITION_ID, PERSON_ID))
.score(6.9)
.type(GradeScheme.DUTCH_GRADE)
.build();
private static final Long ASSIGNMENT_ID = 543L;
private static final Long GROUP_ID = 123456789L;
private static final GradeSummaryDTO GRADE_1 = new GradeSummaryDTO().score(50) // because the score is integer -> 5.0/10.0
.scheme(GradeSummaryDTO.SchemeEnum.DUTCH_GRADE).isScriptGraded(false);
private static final AssignmentSummaryDTO ASSIGNMENT_SUMMARY = new AssignmentSummaryDTO()
.id(ASSIGNMENT_ID)
.name("Assignment");
private static final StudentGroupSummaryDTO GROUP = new StudentGroupSummaryDTO().id(GROUP_ID + 2)
.addMemberUsernamesItem("student");
private static final SubmissionDetailsDTO SUBMISSION = new SubmissionDetailsDTO()
.id(SUBMISSION_ID)
.assignment(ASSIGNMENT_SUMMARY)
.group(GROUP)
.submissionTime(now().minusDays(1))
.addGradesItem(new GradeSummaryDTO().score(70).scheme(GradeSummaryDTO.SchemeEnum.DUTCH_GRADE)
.isScriptGraded(false));
private static final SubmitAssignmentDetailsDTO SUBMIT_ASSIGNMENT_DETAILS = SubmitAssignmentDetailsDTO
.builder()
.id(3L)
.name("Chapter 1")
.module(new ModuleLayer1DTO()
.id(MODULE_ID)
.name("Self Study")
.edition(new EditionSummaryDTO().id(EDITION_ID)))
.description(new Description().text("Read chapter 1"))
.submissions(new ArrayList<>())
.scoreType(GradeScheme.DUTCH_GRADE)
.allowedFileTypes(Collections.emptyList())
.build();
@BeforeEach
void setUp() {
when(assignmentService.getSubmitAssignmentDetails(anyLong())).thenReturn(SUBMIT_ASSIGNMENT_DETAILS);
when(submissionService.getSubmissionsOfAssignmentForGroup(anyLong(), anyLong())).thenReturn(List.of(SUBMISSION));
when(editionService.getSubmitEdition(EDITION_ID)).thenReturn(Optional.of(new SubmitEdition(EDITION_ID, 5.0, null, null, false)));
}
@Test
public void executeSimpleFormula() {
ModuleCalculatedScore expected = ModuleCalculatedScore.builder()
......@@ -423,7 +468,7 @@ public class GradeServiceTest {
@Test
public void getRelevantGradeReturnsNoneWhenNoGrades() {
assertThat(gradeService.getRelevantGrade(List.of(new SubmissionDetailsDTO()
.submissionTime(LocalDateTime.now()).grades(Collections.emptySet())))).isEmpty();
.submissionTime(now()).grades(Collections.emptySet())))).isEmpty();
}
@Test
......@@ -531,6 +576,37 @@ public class GradeServiceTest {
verify(gradeApi).removeHighestGrade(SUBMISSION_ID);
}
@Test
void hasPassedAssignmentNoSubmissions() {
when(submissionService.getSubmissionsOfAssignmentForGroup(anyLong(), anyLong())).thenReturn(List.of());
boolean hasPassed = gradeService.hasPassedAssignment(ASSIGNMENT_ID, GROUP_ID);
verify(assignmentService).getSubmitAssignmentDetails(ASSIGNMENT_ID);
verify(submissionService).getSubmissionsOfAssignmentForGroup(ASSIGNMENT_ID, GROUP_ID);
assertFalse(hasPassed);
}
@Test
void hasPassedAssignmentTrue() {
boolean hasPassed = gradeService.hasPassedAssignment(ASSIGNMENT_ID, GROUP_ID);
verify(assignmentService).getSubmitAssignmentDetails(ASSIGNMENT_ID);
verify(submissionService).getSubmissionsOfAssignmentForGroup(ASSIGNMENT_ID, GROUP_ID);
assertTrue(hasPassed);
}
@Test
void hasPassedAssignmentHasSubmissionsButFailingGrade() {
when(editionService.getSubmitEdition(EDITION_ID)).thenReturn(Optional.of(new SubmitEdition(EDITION_ID, 9.0, null, null, false)));
boolean hasPassed = gradeService.hasPassedAssignment(ASSIGNMENT_ID, GROUP_ID);
verify(assignmentService).getSubmitAssignmentDetails(ASSIGNMENT_ID);
verify(submissionService).getSubmissionsOfAssignmentForGroup(ASSIGNMENT_ID, GROUP_ID);
assertFalse(hasPassed);
}
@Test
void testGetPassingScoreSchemeEnumWithDutchGrade() {
when(editionService.getSubmitEdition(EDITION_ID)).thenReturn(Optional.of(new SubmitEdition(EDITION_ID, 6.0, null, null, false)));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment