Skip to content
Snippets Groups Projects
Commit e7dd0326 authored by Danae Savvidi's avatar Danae Savvidi :laughing:
Browse files

add exception handling & other small fixes

parent 62adb85b
Branches
No related tags found
2 merge requests!260Deploy,!242Resolve "Copy assignments to new edition"
......@@ -38,6 +38,7 @@ import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.opencsv.exceptions.CsvValidationException;
......@@ -242,15 +243,18 @@ public class EditionController {
* @param ids The moduleIds
* @param editionId The edition id
* @return The page to redirect to
* @throws IOException is thrown if any error occurs along the way
*/
@PostMapping("/{editionId}/import-modules")
@PreAuthorize("@authorizationService.canCreateModule(#editionId)")
public String importModules(@RequestParam String ids, @PathVariable Long editionId)
throws IOException {
public String importModules(@RequestParam String ids, @PathVariable Long editionId,
RedirectAttributes redirectAttributes) {
try {
moduleService.copyModulesToEdition(
Arrays.stream(ids.split(",")).filter(x -> !x.isBlank()).map(Long::valueOf).toList(),
editionId);
} catch (Exception e) {
redirectAttributes.addFlashAttribute("import_error", e.getMessage());
}
return "redirect:/edition/" + editionId;
}
......
......@@ -33,6 +33,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import jakarta.validation.Valid;
import nl.tudelft.labracore.api.dto.*;
......@@ -50,6 +51,7 @@ import nl.tudelft.submit.dto.view.statistics.ModuleTableRowDTO;
import nl.tudelft.submit.enums.DivisionsCreateType;
import nl.tudelft.submit.enums.GradableType;
import nl.tudelft.submit.enums.GradeStatistics;
import nl.tudelft.submit.exception.ImportException;
import nl.tudelft.submit.security.AuthorizationService;
import nl.tudelft.submit.service.*;
......@@ -342,15 +344,18 @@ public class ModuleController {
* @param ids The assignmentIds
* @param moduleId The module id
* @return The page to redirect to
* @throws IOException is thrown if any error occurs along the way
*/
@PostMapping("/{moduleId}/import-assignments")
@PreAuthorize("@authorizationService.canCreateAssignment(#moduleId)")
public String importAssignments(@RequestParam String ids, @PathVariable Long moduleId)
throws IOException {
public String importAssignments(@RequestParam String ids, @PathVariable Long moduleId,
RedirectAttributes redirectAttributes) {
try {
assignmentService.copyAssignmentsToModule(
Arrays.stream(ids.split(",")).filter(x -> !x.isBlank()).map(Long::valueOf).toList(),
moduleId);
} catch (ImportException e) {
redirectAttributes.addFlashAttribute("import_error", e.getMessage());
}
return "redirect:/module/" + moduleId;
}
......
/*
* Submit
* Copyright (C) 2020 - Delft University of Technology
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package nl.tudelft.submit.exception;
public class ImportException extends Exception {
public ImportException(String message) {
super(message);
}
}
......@@ -53,6 +53,7 @@ import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentDetailsDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentSummaryDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitGroupSummaryDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitSubmissionViewDTO;
import nl.tudelft.submit.exception.ImportException;
import nl.tudelft.submit.model.SubmitAssignment;
import nl.tudelft.submit.model.note.AssignmentNote;
import nl.tudelft.submit.repository.SubmitAssignmentRepository;
......@@ -123,18 +124,30 @@ public class AssignmentService {
*
* @param assignmentIds assignmentIds the assignments to copy
* @param moduleId moduleId the module to copy to
* @throws IOException is thrown if any error occurs along the way
* @throws ImportException is thrown if an error occurs along the way
*/
public void copyAssignmentsToModule(List<Long> assignmentIds, Long moduleId) throws IOException {
public void copyAssignmentsToModule(List<Long> assignmentIds, Long moduleId) throws ImportException {
String assignmentsDirectory = storageDir + "/assignments";
for (Long assignmentId : assignmentIds) {
SubmitAssignmentCreateDTO newAssignment = mapper.map(getSubmitAssignmentDetails(assignmentId),
SubmitAssignmentDetailsDTO assignment;
try {
assignment = getSubmitAssignmentDetails(assignmentId);
} catch (Exception e) {
throw new ImportException("Could not find assignment: " + assignmentId);
}
SubmitAssignmentCreateDTO newAssignment = mapper.map(assignment,
SubmitAssignmentCreateDTO.class);
newAssignment.setModule(new ModuleIdDTO().id(moduleId));
newAssignment.setName(newAssignment.getName() + " (Copy)");
Long newAssignmentId = addAssignment(newAssignment);
if (assignmentFileExists(assignmentId))
fileService.copyFilesFromFolderToFolder(assignmentsDirectory, assignmentId, newAssignmentId);
try {
fileService.copyFilesFromFolderToFolder(assignmentsDirectory, assignmentId,
newAssignmentId);
} catch (IOException e) {
throw new ImportException(
"Error while trying to copy files of assignment: " + assignmentId);
}
}
}
......
......@@ -17,7 +17,6 @@
*/
package nl.tudelft.submit.service;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
......@@ -39,6 +38,7 @@ import nl.tudelft.submit.dto.view.GradingFormulaViewDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitAssignmentSummaryDTO;
import nl.tudelft.submit.dto.view.labracore.SubmitModuleViewDTO;
import nl.tudelft.submit.enums.DivisionsCreateType;
import nl.tudelft.submit.exception.ImportException;
@Service
public class ModuleService {
......@@ -130,12 +130,13 @@ public class ModuleService {
*
* @param moduleIds the modules to copy
* @param editionId the edition to copy to
* @throws IOException is thrown if any error occurs along the way
* @throws ImportException is thrown if any error occurs along the way
*/
public void copyModulesToEdition(List<Long> moduleIds, Long editionId) throws IOException {
public void copyModulesToEdition(List<Long> moduleIds, Long editionId)
throws ResourceNotFoundException, ImportException {
List<ModuleDetailsDTO> modules = moduleApi.getModulesById(moduleIds).collectList().block();
if (modules == null || modules.isEmpty()) {
throw new ResourceNotFoundException("Could not find modules");
throw new ResourceNotFoundException("Could not find any modules.");
}
for (ModuleDetailsDTO module : modules) {
Long newModuleId = addModuleWithDivisions(ModuleCreateWithDivisionsDTO.builder()
......@@ -147,6 +148,13 @@ public class ModuleService {
assignmentService.copyAssignmentsToModule(
module.getAssignments().stream().map(AssignmentSummaryDTO::getId).toList(), newModuleId);
}
if (modules.size() != moduleIds.size()) {
Set<Long> existingModules = modules.stream().map(ModuleDetailsDTO::getId)
.collect(Collectors.toSet());
String notFoundModules = moduleIds.stream().filter(x -> !existingModules.contains(x))
.map(String::valueOf).collect(Collectors.joining(", "));
throw new ResourceNotFoundException("Could not find modules: " + notFoundModules);
}
}
/**
......
......@@ -151,13 +151,13 @@ module.create_groups.amount = Amount of groups
module.create_groups.amount.enter = Enter amount
module.export_groups = Export groups
module.import = Import modules
module.import.enter = Module IDs separated by comma e.g. "45,2,65"
module.import.enter = Module IDs separated by comma e.g. 45,2,6.
module.import.help = Copy modules to this edition. Assignments are also copied. Remember to adjust dates and divisions/groups.
assignment.id = Assignment ID
assignment.add = Add assignment
assignment.import = Import assignments
assignment.import.enter = Assignment IDs separated by comma e.g. "45,2,65"
assignment.import.enter = Assignment IDs separated by comma e.g. 45,2,6
assignment.import.help = Copy assignments to this module, remember to adjust dates.
assignment.show = Show assignment
assignment.hide = Hide assignment
......
......@@ -39,6 +39,10 @@
<p th:text="#{edition.hide.info}"></p>
</div>
<div class="banner mb-3" data-type="error" th:if="${error != null}">
<p th:text="${error}"></p>
</div>
<h1 class="font-800 mb-3" th:text="|${edition.course.name} - ${edition.name}|"></h1>
<div class="flex gap-3 wrap mb-5 | sm:vertical">
......
......@@ -49,6 +49,10 @@
</div>
</div>
<div class="banner mb-3" data-type="error" th:if="${import_error != null}">
<p th:text="${import_error}"></p>
</div>
<div>
<div class="flex space-between align-center">
<h3 class="font-500 mb-2">Modules</h3>
......
......@@ -33,17 +33,16 @@
th:action="@{|/${importTo}/${id}/import-${type}s|}"
method="post"
class="flex vertical p-7">
<h2 class="underlined font-500" th:text="#{|${type}.import|}"></h2>
<div class="grid col-2 gap-3 align-center" style="--col-1: minmax(0, 6rem)">
<div>
<label for="ids" th:text="#{|${type}.import|}"></label>
<div class="flex underlined">
<h2 class="font-500" th:text="#{|${type}.import|}"></h2>
<div class="tooltip">
<span class="tooltip__control fa-solid fa-question"></span>
<div role="tooltip" style="white-space: initial; min-width: 24rem">
<div role="tooltip" style="white-space: initial; min-width: 16rem">
<p th:text="#{|${type}.import.help|}"></p>
</div>
</div>
</div>
<div class="grid col-1 align-center">
<input
id="ids"
th:name="ids"
......
......@@ -55,6 +55,10 @@
</div>
</div>
<div class="banner mb-3" data-type="error" th:if="${import_error != null}">
<p th:text="${import_error}"></p>
</div>
<div class="flex space-between align-center mb-3">
<h2 class="font-500" th:text="#{module.assignments}"></h2>
<div class="flex gap-3">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment