Add users to projects

This commit is contained in:
neviyn 2021-03-31 20:03:00 +01:00
parent 2c26e8b013
commit f61fd78287
5 changed files with 65 additions and 58 deletions

View File

@ -17,6 +17,7 @@ import javax.persistence.OneToMany
open class User(
var username: String = "INVALID",
var email: String = "INVALID",
@JsonIgnore
var password: String = "INVALID",
@ManyToMany(cascade = [CascadeType.ALL])
@JsonIgnore

View File

@ -99,7 +99,9 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
@PreAuthorize("hasPermission(#id, 'Long', '')")
fun getProject(@PathVariable id: Long, model: Model) : String {
val project = projectRepository.findById(id).get()
val nonMembers = userRepository.findByIdNotIn(project.members.map { it.id!! })
model.addAttribute("project", project)
model.addAttribute("nonMembers", nonMembers)
return "project"
}
@ -109,27 +111,20 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
return projectRepository.findById(id).get().events
}
@GetMapping("/adduser")
@PreAuthorize("hasPermission(#id, 'Long', '')")
fun addUserToProjectForm(@PathVariable id: Long, model: Model) : String{
val project = projectRepository.findById(id).get()
val users = userRepository.findByIdNotIn(project.members.map { it.id!! }).map { SimpleUser(it.id!!, it.username) }
model.addAttribute("available_users", users)
return "addprojectuser"
}
@PostMapping("/adduser")
@PreAuthorize("hasPermission(#id, 'Long', '')")
fun addUserToProject(@PathVariable id: Long, @RequestBody u: UserID) {
val user = userRepository.findById(u.id).get()
fun addUserToProject(@PathVariable id: Long, @RequestParam("uid") uid: Long) : String {
val user = userRepository.findById(uid).get()
val project = projectRepository.findById(id).get()
project.members.add(user)
user.projects.add(project)
projectRepository.save(project)
return "redirect:/project/$id"
}
@PostMapping("/removeuser")
@PreAuthorize("hasPermission(#id, 'Long', '')")
fun removeUserFromProject(@PathVariable id: Long, @RequestParam("id") uid: Long, model: Model) : String{
fun removeUserFromProject(@PathVariable id: Long, @RequestParam("id") uid: Long) : String{
val project = projectRepository.findById(id).get()
// Don't allow projects to have no members
if(project.members.size == 1) return "redirect:/project/$id"

View File

@ -2,10 +2,6 @@ package uk.co.neviyn.projectplanner
import java.time.LocalDateTime
data class UserID(val id: Long)
data class SimpleUser(val id: Long, val username: String)
data class DisplayUser(val id: Long, val username: String, val email: String, val password: String, val oldPassword: String)
data class NewProject(val title: String)

View File

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments :: baseHeader(~{::title})">
<title>Add user to project | Project Planner</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js"></script>
<script th:inline="javascript">
const userList = [[${available_users}]];
const options = {
valueNames: ['id', 'username'],
// Since there are no elements in the list, this will be used as template.
item: '<li><h3 class="username"></h3></li>'
};
var list = new List('users', options, userList)
</script>
</head>
<body>
<div id="users">
<label>Search
<input class="search" placeholder="Search" />
</label>
<ul class="list"></ul>
</div>
</body>
</html>

View File

@ -4,8 +4,9 @@
<title th:text="${project.title} + ' | Project Planner'">Project Planner</title>
</head>
<head>
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.js" crossorigin="anonymous"></script>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css" rel="stylesheet">
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.js"></script>
<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js"></script>
<script>
window.onload = function () {
let calendarEl = document.getElementById('calendar');
@ -25,6 +26,14 @@
calendar.render();
};
</script>
<script th:inline="javascript">
window.onload = function () {
const options = {
valueNames: ['username'],
};
new List('user-list', options);
}
</script>
<title></title>
</head>
<body>
@ -38,7 +47,9 @@
<div class="row justify-content-center">
<div class="col-2">
<div class="list-group mb-3">
<button class="list-group-item active" data-bs-toggle="modal" data-bs-target="#newEventModal">Add Event...</button>
<button class="list-group-item active" data-bs-target="#newEventModal" data-bs-toggle="modal">Add
Event...
</button>
</div>
<div class="list-group">
<div class="list-group-item active">Members:</div>
@ -46,32 +57,37 @@
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between align-items-center">
<p th:text="${member.username}">username</p>
<form class="form-floating mb-3" th:action="@{/project/{pid}/removeuser(pid=${id})}" method="post">
<input type="hidden" name="id" th:value="${member.id}">
<button class="btn btn-outline-danger btn-sm" type="submit"><i class="bi bi-x-circle text-danger"></i></button>
<form class="form-floating mb-3" method="post"
th:action="@{/project/{pid}/removeuser(pid=${id})}">
<input name="id" th:value="${member.id}" type="hidden">
<button class="btn btn-outline-danger btn-sm" type="submit"><i
class="bi bi-x-circle text-danger"></i></button>
</form>
</div>
</div>
</div>
<a th:href="@{/{id}/adduser(id=${id})}" class="list-group-item list-group-item-action list-group-item-secondary">Add member</a>
<button class="list-group-item list-group-item-action list-group-item-secondary"
data-bs-target="#newMemberModal"
data-bs-toggle="modal">Add member
</button>
</div>
</div>
<div class="col-10">
<div id="calendar" class="d-flex flex-fill"></div>
<div class="d-flex flex-fill" id="calendar"></div>
</div>
</div>
</div>
<div id="newEventModal" class="modal" tabindex="-1">
<!-- Modal for creating new events -->
<div class="modal" id="newEventModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">New Event</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"></button>
</div>
<div class="modal-body">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="titleInput">
<input class="form-control" id="titleInput" type="text">
<label for="titleInput">Event Title</label>
</div>
<div class="form-floating mb-3">
@ -79,17 +95,42 @@
<label for="descriptionInput">Event Description</label>
</div>
<div class="form-floating mb-3">
<input type="datetime-local" class="form-control" id="startTimeInput">
<input class="form-control" id="startTimeInput" type="datetime-local">
<label for="startTimeInput">Start Time</label>
</div>
<div class="form-floating mb-3">
<input type="datetime-local" class="form-control" id="endTimeInput">
<input class="form-control" id="endTimeInput" type="datetime-local">
<label for="endTimeInput">End Time</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Add Event</button>
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
<button class="btn btn-primary" type="button">Add Event</button>
</div>
</div>
</div>
</div>
<!-- Modal for adding members to a project -->
<div class="modal" id="newMemberModal" tabindex="-1">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Member</h5>
<button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"></button>
</div>
<div class="modal-body d-flex flex-column" id="user-list">
<p class="text-center lead">Click a username to add them to this project.</p>
<label class="mb-2">
<input class="search form-control w-100" placeholder="Search" type="search"/>
</label>
<div class="list list-group">
<form class="list-group-item list-group-item-action" method="post" th:action="@{/project/{pid}/adduser(pid=${id})}"
th:each="member : ${nonMembers}">
<input name="uid" th:value="${member.id}" type="hidden"/>
<button class="btn btn-block h-100 w-100 username" th:text="${member.username}"
type="submit"></button>
</form>
</div>
</div>
</div>
</div>