Skip to content
Snippets Groups Projects
Commit 6625f7b9 authored by Otto Visser's avatar Otto Visser
Browse files

Merge branch 'development' into '22-differentiate-between-no-access-and-error'

# Conflicts:
#   src/main/resources/templates/assignment/view.html
parents 0a0d6537 2221e673
No related branches found
No related tags found
1 merge request!16Resolve "Differentiate between no access and error"
Showing
with 91 additions and 37 deletions
......@@ -29,6 +29,7 @@ import javax.validation.Valid;
import nl.tudelft.labracore.api.dto.*;
import nl.tudelft.labracore.lib.security.user.AuthenticatedPerson;
import nl.tudelft.librador.dto.view.View;
import nl.tudelft.submit.csv.CSVService;
import nl.tudelft.submit.dto.create.SubmitAssignmentCreateDTO;
import nl.tudelft.submit.dto.create.grading.SubmitGradeCreateDTO;
......@@ -36,6 +37,7 @@ import nl.tudelft.submit.dto.create.note.AssignmentNoteCreateDTO;
import nl.tudelft.submit.dto.patch.SubmitAssignmentPatchDTO;
import nl.tudelft.submit.dto.patch.grading.AssignmentGradeImportDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentDetailsDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitSubmissionViewDTO;
import nl.tudelft.submit.model.Signature;
import nl.tudelft.submit.security.AuthorizationService;
import nl.tudelft.submit.service.*;
......@@ -124,7 +126,8 @@ public class AssignmentController {
List<SubmissionDetailsDTO> submissions = submissionService
.getSubmissionsOfAssignmentForGroup(id, groupId);
Collections.reverse(submissions);
model.addAttribute("submissions", submissions);
model.addAttribute("submissions",
View.convert(submissions, SubmitSubmissionViewDTO.class));
model.addAttribute("canMakeSubmission",
submissionService.canMakeSubmission(id, groupId));
......
......@@ -80,6 +80,13 @@ public class GradeController {
return "redirect:/group/{groupId}?assignment={assignmentId}&submission=" + create.getSubmissionId();
}
@PostMapping("/group/remove-highest/{groupId}/{submissionId}")
@PreAuthorize("@authorizationService.hasStaffRoleForGroup(#groupId)") // TODO change
public String removeHighestGradeForGroup(@PathVariable Long groupId, @PathVariable Long submissionId) {
gradeService.removeHighestGrade(submissionId);
return "redirect:/group/{groupId}";
}
@PostMapping("/assignment/{assignmentId}")
@PreAuthorize("@authorizationService.canGiveGrade(#create.submission.id)")
public String addGradeForAssignment(@PathVariable Long assignmentId,
......@@ -91,6 +98,14 @@ public class GradeController {
return "redirect:/assignment/{assignmentId}/submissions";
}
@PostMapping("/assignment/remove-highest/{assignmentId}/{submissionId}")
@PreAuthorize("@authorizationService.hasTeacherRoleInAssignment(#assignmentId)")
public String removeHighestGradeForAssignment(@PathVariable Long assignmentId,
@PathVariable Long submissionId) {
gradeService.removeHighestGrade(submissionId);
return "redirect:/assignment/{assignmentId}/submissions";
}
public class TestCalculatedScore extends CalculatedScore {
public TestCalculatedScore(Id id, @NotNull Double score, @NotNull Grade.SchemeEnum type) {
super(id, score, type);
......
......@@ -39,7 +39,7 @@ public class HomeController {
@GetMapping
public String homePage(@AuthenticatedPerson(required = false) Person person, Model model) {
model.addAttribute("authPerson", person);
return "index";
return person == null ? "index" : "redirect:edition/enrolled";
}
/**
......
......@@ -17,7 +17,7 @@
*/
package nl.tudelft.submit.dto.view.statistics;
import java.util.Map;
import java.util.SortedMap;
import javax.validation.constraints.NotNull;
......@@ -38,6 +38,6 @@ public class EditionModuleGradesDTO {
private ModuleCalculatedScore moduleGrade;
@NotNull
private Map<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades;
private SortedMap<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades;
}
......@@ -17,7 +17,7 @@
*/
package nl.tudelft.submit.dto.view.statistics;
import java.util.Map;
import java.util.SortedMap;
import javax.validation.constraints.NotNull;
......@@ -42,6 +42,6 @@ public class EditionTableRowDTO {
private Boolean isPassing;
@NotNull
private Map<ModuleSummaryDTO, EditionModuleGradesDTO> moduleGrades;
private SortedMap<ModuleSummaryDTO, EditionModuleGradesDTO> moduleGrades;
}
......@@ -17,7 +17,7 @@
*/
package nl.tudelft.submit.dto.view.statistics;
import java.util.Map;
import java.util.SortedMap;
import javax.validation.constraints.NotNull;
......@@ -47,6 +47,6 @@ public class ModuleTableRowDTO {
private Boolean isPassing;
@NotNull
private Map<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades;
private SortedMap<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades;
}
......@@ -80,7 +80,7 @@ public enum TokenType {
"FAILED"
),
FUNCTION_NAME(
"abs|max|min"
"abs|max|min|sqrt|avg|clamp"
),
VARIABLE(
"[A-Za-z_][A-Za-z0-9_]*"
......
......@@ -51,7 +51,7 @@ public class LoginSecurityConfigurerAdapter extends LabradorSecurityConfigurerAd
// Homepage can be loaded without authentication, but all other request need authentication first
http.authorizeRequests()
.antMatchers("/", "/css/**", "/js/**", "/img/**", "/webjars/**", "/socket-endpoint/**",
"/privacy")
"/privacy", "/favicon.ico")
.permitAll()
.anyRequest().authenticated();
}
......
......@@ -146,8 +146,14 @@ public class AssignmentService {
* @return The id of the patched assignment.
*/
public Long patchAssignment(Long id, SubmitAssignmentPatchDTO assignmentPatchDTO) {
id = assignmentApi.patchAssignment(id, mapper.map(assignmentPatchDTO, AssignmentPatchDTO.class))
.block();
AssignmentPatchDTO patch = mapper.map(assignmentPatchDTO, AssignmentPatchDTO.class);
if (patch.getAcceptLateSubmissions() == null) {
patch.setAcceptLateSubmissions(false);
}
if (patch.getAllowedFileTypes() == null) {
patch.setAllowedFileTypes(Collections.emptyList());
}
id = assignmentApi.patchAssignment(id, patch).block();
assignmentRepository.save(assignmentPatchDTO.apply(getOrCreateSubmitAssignment(id)));
return id;
}
......
......@@ -65,6 +65,10 @@ public class FormulaService {
functions.put("abs", l -> Math.abs((double) l.get(0)));
functions.put("max", l -> Math.max((double) l.get(0), (double) l.get(1)));
functions.put("min", l -> Math.min((double) l.get(0), (double) l.get(1)));
functions.put("clamp",
l -> Math.max((double) l.get(0), Math.min((double) l.get(1), (double) l.get(2))));
functions.put("sqrt", l -> Math.sqrt((double) l.get(0)));
functions.put("avg", l -> l.stream().mapToDouble(x -> (double) x).average().getAsDouble());
FUNCTIONS = functions;
}
......
......@@ -141,6 +141,9 @@ public class GradeService {
return Optional.ofNullable(convertToScore(formula, result));
} catch (InvalidFormulaException e) {
return Optional.empty();
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
......@@ -628,7 +631,7 @@ public class GradeService {
* @return The generated variable
*/
public String generateVariableName(String name) {
return name.toLowerCase().replace(" ", "_");
return name.toLowerCase().replace(" ", "_").replaceAll("[^A-Za-z0-9_]+", "");
}
/**
......@@ -716,4 +719,13 @@ public class GradeService {
return gradeApi.addGrade(create).block();
}
/**
* Removed the highest grade for a submission
*
* @param submissionId The id of the submission
*/
public void removeHighestGrade(Long submissionId) {
gradeApi.removeHighestGrade(submissionId).block();
}
}
......@@ -98,19 +98,23 @@ public class StatisticsService {
Optional<Double> passingScore = gradeType == Grade.SchemeEnum.PASS_FAIL ? Optional.of(1.0)
: editionPassingScore;
Map<ModuleSummaryDTO, EditionModuleGradesDTO> moduleGrades = modules.stream()
SortedMap<ModuleSummaryDTO, EditionModuleGradesDTO> moduleGrades = new TreeMap<>(
Comparator.comparingLong(ModuleSummaryDTO::getId));
moduleGrades.putAll(modules.stream()
.collect(Collectors.toMap(m -> mapper.map(m, ModuleSummaryDTO.class), module -> {
ModuleCalculatedScore moduleGrade = gradeService
.getModuleScore(new PersonIdDTO().id(person.getId()),
new ModuleIdDTO().id(module.getId()))
.orElse(null);
Map<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades = getAssignmentGradesForModule(
SortedMap<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades = new TreeMap<>(
Comparator.comparingLong(AssignmentSummaryDTO::getId));
assignmentGrades.putAll(getAssignmentGradesForModule(
module, submissions.get(module.getId()),
groups.get(module.getId()).stream().filter(g -> g.getMemberUsernames()
.contains(person.getUsername())).findAny()
.map(g -> mapper.map(g, StudentGroupSummaryDTO.class)).orElse(null));
.map(g -> mapper.map(g, StudentGroupSummaryDTO.class)).orElse(null)));
return new EditionModuleGradesDTO(moduleGrade, assignmentGrades);
}));
})));
return EditionTableRowDTO.builder()
.person(person)
......@@ -312,10 +316,12 @@ public class StatisticsService {
.build();
}
private Map<AssignmentSummaryDTO, GradeSummaryDTO> getAssignmentGradesForModule(ModuleDetailsDTO module,
private SortedMap<AssignmentSummaryDTO, GradeSummaryDTO> getAssignmentGradesForModule(
ModuleDetailsDTO module,
Map<StudentGroupSummaryDTO, List<SubmissionDetailsDTO>> submissions,
StudentGroupSummaryDTO group) {
Map<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades = new HashMap<>();
SortedMap<AssignmentSummaryDTO, GradeSummaryDTO> assignmentGrades = new TreeMap<>(
Comparator.comparingLong(AssignmentSummaryDTO::getId));
for (AssignmentSummaryDTO assignment : module.getAssignments()) {
if (group == null || !submissions.containsKey(group)) {
assignmentGrades.put(assignment, null);
......
......@@ -108,18 +108,25 @@ public class StudentGroupService {
assignment.setScoreType(assignmentService.getOrCreateSubmitAssignment(a.getId())
.getScoreType());
return assignment;
},
a -> submissionService.getSubmissionsOfAssignmentForGroup(a.getId(), id)
}, a -> {
var submissions = submissionService
.getSubmissionsOfAssignmentForGroup(a.getId(), id)
.stream()
.sorted(Comparator.comparing(SubmissionDetailsDTO::getSubmissionTime)
.reversed())
.map(s -> {
SubmitSubmissionViewDTO view = mapper.map(s,
SubmitSubmissionViewDTO.class);
view.setIsLatest(false);
view.setFeedback(
feedbackService.getAllFeedbackPerSubmission(s.getId()));
return view;
}).collect(Collectors.toList()))));
}).collect(Collectors.toList());
if (!submissions.isEmpty()) {
submissions.get(0).setIsLatest(true);
}
return submissions;
})));
group.setSubmissionMap(assignments);
if (isStaff) {
......
......@@ -81,7 +81,7 @@ labrador:
saved-request-aware: true
# This field holds the url that the user is redirected to after successful login as well as after the logout.
# Therefore, check if a url is accessible without authentication before setting it to be the success-url.
success-url: /edition/enrolled
success-url: /
# For the SAML security configurations, we refer to documentation here:
# https://github.com/ulisesbocchio/spring-boot-security-saml
......
......@@ -54,7 +54,7 @@
">
<span th:text="#{mail.notification_preference.before}"></span>
<a style="color: #00A6D6; text-decoration: none;" target="_blank"
href="http://localhost:8083/settings" th:text="#{mail.here}"></a>
href="https://submit.tudelft.nl/settings" th:text="#{mail.here}"></a>
<span th:text="#{mail.notification_preference.after}"></span>
</p>
</div>
......
......@@ -54,7 +54,7 @@
">
<span th:text="#{mail.notification_preference.before}"></span>
<a style="color: #00A6D6; text-decoration: none;" target="_blank"
href="http://localhost:8083/settings" th:text="#{mail.here}"></a>
href="https://submit.tudelft.nl/settings" th:text="#{mail.here}"></a>
<span th:text="#{mail.notification_preference.after}"></span>
</p>
</div>
......
......@@ -54,7 +54,7 @@
">
<span th:text="#{mail.notification_preference.before}"></span>
<a style="color: #00A6D6; text-decoration: none;" target="_blank"
href="http://localhost:8083/settings" th:text="#{mail.here}"></a>
href="https://submit.tudelft.nl/settings" th:text="#{mail.here}"></a>
<span th:text="#{mail.notification_preference.after}"></span>
</p>
</div>
......
......@@ -52,7 +52,7 @@
">
<span th:text="#{mail.notification_preference.before}"></span>
<a style="color: #00A6D6; text-decoration: none;" target="_blank"
href="http://localhost:8083/settings" th:text="#{mail.here}"></a>
href="https://submit.tudelft.nl/settings" th:text="#{mail.here}"></a>
<span th:text="#{mail.notification_preference.after}"></span>
</p>
</div>
......
......@@ -60,7 +60,7 @@
">
<span th:text="#{mail.notification_preference.before}"></span>
<a style="color: #00A6D6; text-decoration: none;" target="_blank"
href="http://localhost:8083/settings" th:text="#{mail.here}"></a>
href="https://submit.tudelft.nl/settings" th:text="#{mail.here}"></a>
<span th:text="#{mail.notification_preference.after}"></span>
</p>
</div>
......
......@@ -296,6 +296,7 @@ submission.download_files = Download files
submission.new_grade = New grade
submission.grade_submission = Grade this submission
submission.set_grade = Set grade
submission.not_latest = You can only give feedback to the latest submission
feedback.text = Textual feedback
submission.received.title = Your submission was successfully received
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment