Skip to content
Snippets Groups Projects

Allow feedback to be flagged

Files

/*
* Queue - A Queueing system that can be used to handle labs in higher education
* Copyright (C) 2016-2024 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.queue.controller;
import java.util.Comparator;
import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import lombok.AllArgsConstructor;
import nl.tudelft.labracore.lib.security.user.AuthenticatedPerson;
import nl.tudelft.labracore.lib.security.user.Person;
import nl.tudelft.librador.dto.view.View;
import nl.tudelft.queue.PageUtil;
import nl.tudelft.queue.cache.PersonCacheManager;
import nl.tudelft.queue.dto.view.FeedbackViewDTO;
import nl.tudelft.queue.model.Feedback;
import nl.tudelft.queue.repository.FeedbackRepository;
import nl.tudelft.queue.service.FeedbackService;
@Controller
@RequestMapping("/feedback")
@AllArgsConstructor
public class FeedbackController {
private FeedbackService fs;
private PersonCacheManager pCache;
private FeedbackRepository fr;
/**
* Maps the own feedback url to a page. The Feedback page displays feedback for the currently
* authenticated user.
*
* @param person The person that is currently authenticated.
* @param model The model to be filled out for Thymeleaf resolution.
* @param pageable The Pageable object representing the current page state.
* @return The feedback page location to be filled in by Thymeleaf.
*/
@GetMapping
@PreAuthorize("@permissionService.canViewOwnFeedback()")
public String ownFeedback(@AuthenticatedPerson Person person,
Model model, Pageable pageable) {
fillInFeedbackModel(person.getId(), person, model, pageable, false);
return "home/feedback";
}
/**
* Maps the feedback url to a page. The Feedback page displays feedback for a user with the given ID. This
* endpoint is also used by TAM.
*
* @param person The person that is currently authenticated.
* @param id The id of the person for which feedback will be shown.
* @param model The model to be filled out for Thymeleaf resolution.
* @param pageable The Pageable object representing the current page state.
* @return The feedback page location to be filled in by Thymeleaf.
*/
@GetMapping("/{id}")
@PreAuthorize("@permissionService.canViewFeedback(#id)")
public String feedback(@AuthenticatedPerson Person person, @PathVariable("id") Long id,
Model model, Pageable pageable) {
fillInFeedbackModel(id, person, model, pageable, false);
return "home/feedback";
}
@GetMapping("/{id}/manager")
@PreAuthorize("@permissionService.canViewFeedback(#id)")
public String feedbackManager(@AuthenticatedPerson Person person, @PathVariable("id") Long id,
Model model, Pageable pageable) {
fillInFeedbackModel(id, person, model, pageable, true);
return "home/feedback";
}
@PostMapping("/report")
public String reportFeedback(@RequestParam Long request, @RequestParam Long assistant,
@RequestParam String callback) {
fs.reportFeedback(new Feedback.Id(request, assistant));
return "redirect:" + callback + "?success";
}
/**
* Fills in the model for a page where feedback is shown to the user.
*
*
* @param assistantId The id of the user to find assistant for (this could be the current
* user).
* @param person The person that is currently authenticated.
* @param model The model that is to be filled.
* @param pageable The pageable containing information on how much feedback needs to be
* shown.
* @param restrictToCourseManager Used to restrict feedback to the courses a manager teaches.
* @throws AccessDeniedException In the case that a teacher purposefully adds a teacher as a TA to view
* their feedback.
*/
private void fillInFeedbackModel(Long assistantId, Person person, Model model, Pageable pageable,
Boolean restrictToCourseManager) {
var assistant = pCache.getRequired(assistantId);
// Anonymise feedback if viewing own feedback
List<Feedback> feedback = assistantId.equals(person.getId())
? fr.findByAssistantAnonymised(assistantId)
: fr.findByAssistant(assistantId);
// Textual feedback filtered on course manager, stars are not filtered
List<Feedback> textualFeedback = feedback.stream()
.filter(f -> f.getFeedback() != null && !f.getFeedback().isBlank())
.toList();
if (restrictToCourseManager) {
textualFeedback = fs.filterFeedbackForManagerCourses(textualFeedback);
}
model.addAttribute("assistant", assistant);
model.addAttribute("feedback",
PageUtil.toPage(pageable, textualFeedback,
Comparator.comparing(Feedback::getLastUpdatedAt).reversed())
.map(fb -> View.convert(fb, FeedbackViewDTO.class)));
model.addAttribute("stars", fs.countRatings(feedback));
}
}
Loading