Skip to content

Commit

Permalink
Merge pull request #14 from ConnorMarcus/project-view-page-noah
Browse files Browse the repository at this point in the history
Project view page noah
  • Loading branch information
Noahh01 authored Nov 9, 2023
2 parents f0c45a6 + cb1de62 commit cca55d0
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package sysc4806.project.controllers;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CustomErrorController implements ErrorController {

@RequestMapping("/error")
public String handleError() {
return "error";
}
}
98 changes: 80 additions & 18 deletions src/main/java/sysc4806/project/controllers/ProjectController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,29 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import sysc4806.project.models.ApplicationUser;
import sysc4806.project.models.Professor;
import sysc4806.project.models.Project;
import sysc4806.project.models.UserDetails;
import org.springframework.web.bind.annotation.*;
import sysc4806.project.models.*;
import sysc4806.project.repositories.ApplicationUserRepository;
import sysc4806.project.repositories.ProjectRepository;
import sysc4806.project.util.AuthenticationHelper;
import sysc4806.project.services.ApplicationUserService;
import java.util.List;

import static sysc4806.project.util.AuthenticationHelper.PROFESSOR_ROLE;

import static sysc4806.project.util.AuthenticationHelper.*;

@Controller
public class ProjectController {

@Autowired
private ProjectRepository projectRepository;

@Autowired
private ApplicationUserRepository applicationUserRepository;

@Autowired
private ApplicationUserService applicationUserService;

@GetMapping(path = "/createProject")
@Secured(PROFESSOR_ROLE)
public String showProjectForm(Model model) {
Expand All @@ -40,14 +37,79 @@ public String showProjectForm(Model model) {
@PostMapping(path="/createProject")
@Secured(PROFESSOR_ROLE)
public String createProject(@ModelAttribute("project") Project project) {
Professor professor = (Professor) this.getCurrentUser();
Professor professor = (Professor) applicationUserService.getCurrentUser();
project.setProfessor(professor);
projectRepository.save(project);
return "redirect:/home"; //Need to redirect to project list VIEW --> NOAH
return "redirect:/viewProjects";
}

@GetMapping(path = "/viewProjects")
public String viewProjectsPage(Model model) throws Exception {
List<Project> projects = (List<Project>) projectRepository.findAll();
model.addAttribute("projects", projects);

boolean isProfessor = applicationUserService.isCurrentUserProfessor();
model.addAttribute("isProfessor", isProfessor);

if (isProfessor) {
Professor professor = (Professor) applicationUserService.getCurrentUser();
model.addAttribute("professorUser", professor);
} else {
Student student = (Student) applicationUserService.getCurrentUser();
model.addAttribute("studentUser", student);
}
return "viewProjects";
}

@DeleteMapping( "/deleteProject/{projectId}")
public String deleteProject(@PathVariable Long projectId) {
Project project = projectRepository.findById(projectId).orElse(null);
if (project != null) {
disassociateProject(project);
projectRepository.delete(project);
return "viewProjects";
} else {
return "error";
}
}

@PatchMapping("/project/{projectId}/addStudent/{userId}")
public String addStudentToProject(@PathVariable Long projectId, @PathVariable Long userId) {
Project project = projectRepository.findById(projectId).orElse(null);
Student student = (Student) applicationUserRepository.findById(userId).orElse(null);
if (project != null && student != null) {
project.addStudent(student);
student.setProject(project);
projectRepository.save(project);
return "viewProjects";
}
return "error";
}

@PatchMapping("/project/{projectId}/removeStudent/{userId}")
public String removeStudentFromProject(@PathVariable Long projectId, @PathVariable Long userId) {
Project project = projectRepository.findById(projectId).orElse(null);
Student student = (Student) applicationUserRepository.findById(userId).orElse(null);
if (project != null && student != null) {
project.removeStudent(student);
student.setProject(null);
projectRepository.save(project);
return "viewProjects";
}
return "error";
}

private ApplicationUser getCurrentUser() {
UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return applicationUserRepository.findApplicationUserByEmail(user.getUsername());
/**
* Disassociates a project from students and professor
* @param project The project to disassociate
*/
private void disassociateProject(Project project) {
for (Student s: project.getStudents()) {
s.setProject(null);
applicationUserRepository.save(s);
}
Professor professor = project.getProfessor();
professor.removeProject(project);
applicationUserRepository.save(professor);
}
}
18 changes: 17 additions & 1 deletion src/main/java/sysc4806/project/models/Professor.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class Professor extends ApplicationUser {

private Date oralPresentationAvailability;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "professor")
@OneToMany(fetch = FetchType.EAGER, mappedBy = "professor")
private List<Project> projects;

public Professor() {}
Expand All @@ -37,4 +37,20 @@ public Date getOralPresentationAvailability() {
public void setOralPresentationAvailability(Date oralPresentationAvailability) {
this.oralPresentationAvailability = oralPresentationAvailability;
}

/**
* Gets list of projects professor is supervising
* @return List<Project> the list of projects
*/
public List<Project> getProjects() {
return projects;
}

/**
* Remove Project from the Professors projects list
* @param project Project to be removed from the project
*/
public void removeProject(Project project) {
projects.remove(project);
}
}
8 changes: 4 additions & 4 deletions src/main/java/sysc4806/project/models/Project.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package sysc4806.project.models;

import jakarta.persistence.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
Expand All @@ -23,7 +21,7 @@ public class Project {

private List<Program> restrictions;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "project")
@OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER, mappedBy = "project")
private List<Student> students;

@ManyToOne
Expand Down Expand Up @@ -149,7 +147,9 @@ public List<Student> getStudents() {
* @param student Student to be added to the project
*/
public void addStudent(Student student) {
students.add(student);
if (students.size() < maxStudents) {
students.add(student);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package sysc4806.project.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import sysc4806.project.models.*;
import sysc4806.project.repositories.ApplicationUserRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static sysc4806.project.util.AuthenticationHelper.PROFESSOR_ROLE;
import static sysc4806.project.util.AuthenticationHelper.getUserRole;

@Service
public class ApplicationUserService {
@Autowired
ApplicationUserRepository applicationUserRepository;

/**
* Gets the current user
* @return The current application user
*/
public ApplicationUser getCurrentUser() {
UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return applicationUserRepository.findApplicationUserByEmail(user.getUsername());
}


/**
* Check if the current user is Professor
* @return True if the current user is Professor
*/
public boolean isCurrentUserProfessor() throws Exception {
ApplicationUser currentUser = getCurrentUser();
return Objects.equals(getUserRole(currentUser), PROFESSOR_ROLE);
}
}
59 changes: 59 additions & 0 deletions src/main/resources/static/css/ViewProjectsStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
text-align: center;
margin-top: 50px;
color: #333;
}

h1 {
margin-bottom: 30px;
}

table {
margin-left: auto;
margin-right: auto;
border-collapse: collapse;
color: #333;
}

th, td {
border: 2px solid #dddddd;
padding: 8px;
background-color: #fff;
}

ul {
list-style-type: none;
margin: 0;
padding: 0;
}

li {
margin: 5px 0;
}

button {
color: #fff;
padding: 10px 15px;
border: none;
border-radius: 3px;
cursor: pointer;
}

.delete {
background-color: #ff0000;
}

.join, .leave, .create {
background-color: #0056b3;
}

.create {
font-size: 15px;
margin-top: 30px;
}

button:hover {
opacity: 70%;
}
39 changes: 39 additions & 0 deletions src/main/resources/static/js/viewProjectsAction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
$(document).ready(function() {
const baseUrl = window.location.origin;
const patchMethod = "PATCH";
const token = $("meta[name='_csrf']").attr("content");
const header = $("meta[name='_csrf_header']").attr("content");

$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});

function makeAjaxCall(method, endpointUrl) {
$.ajax({
type: method,
url: baseUrl + endpointUrl
})
.done(function () {
window.location.reload();
});
}

function getProjectID(elem) {
return $(elem).parent().attr("project-id")
}

$('.delete').on("click", function() {
const deleteEndpoint = "/deleteProject/" + getProjectID(this);
makeAjaxCall("DELETE", deleteEndpoint);
});

$('.join').on("click", function() {
const joinEndpoint = "/project/" + getProjectID(this) + "/addStudent/" + $(this).attr("user-id");
makeAjaxCall(patchMethod, joinEndpoint);
});

$('.leave').on("click", function() {
const leaveEndpoint = "/project/" + getProjectID(this) + "/removeStudent/" + $(this).attr("user-id");
makeAjaxCall(patchMethod, leaveEndpoint);
});
});
16 changes: 16 additions & 0 deletions src/main/resources/templates/error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<style>
body {
margin-left: 15px;
}
</style>
</head>
<body>
<h1>Oops! An error occurred</h1>
<p>We're sorry, but something went wrong.</p>
<a href="/home">Go to homepage</a>
</body>
</html>
Loading

0 comments on commit cca55d0

Please sign in to comment.