Add users to projects
This commit is contained in:
parent
2c26e8b013
commit
f61fd78287
@ -17,6 +17,7 @@ import javax.persistence.OneToMany
|
|||||||
open class User(
|
open class User(
|
||||||
var username: String = "INVALID",
|
var username: String = "INVALID",
|
||||||
var email: String = "INVALID",
|
var email: String = "INVALID",
|
||||||
|
@JsonIgnore
|
||||||
var password: String = "INVALID",
|
var password: String = "INVALID",
|
||||||
@ManyToMany(cascade = [CascadeType.ALL])
|
@ManyToMany(cascade = [CascadeType.ALL])
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
|
@ -99,7 +99,9 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
|
|||||||
@PreAuthorize("hasPermission(#id, 'Long', '')")
|
@PreAuthorize("hasPermission(#id, 'Long', '')")
|
||||||
fun getProject(@PathVariable id: Long, model: Model) : String {
|
fun getProject(@PathVariable id: Long, model: Model) : String {
|
||||||
val project = projectRepository.findById(id).get()
|
val project = projectRepository.findById(id).get()
|
||||||
|
val nonMembers = userRepository.findByIdNotIn(project.members.map { it.id!! })
|
||||||
model.addAttribute("project", project)
|
model.addAttribute("project", project)
|
||||||
|
model.addAttribute("nonMembers", nonMembers)
|
||||||
return "project"
|
return "project"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,27 +111,20 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
|
|||||||
return projectRepository.findById(id).get().events
|
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")
|
@PostMapping("/adduser")
|
||||||
@PreAuthorize("hasPermission(#id, 'Long', '')")
|
@PreAuthorize("hasPermission(#id, 'Long', '')")
|
||||||
fun addUserToProject(@PathVariable id: Long, @RequestBody u: UserID) {
|
fun addUserToProject(@PathVariable id: Long, @RequestParam("uid") uid: Long) : String {
|
||||||
val user = userRepository.findById(u.id).get()
|
val user = userRepository.findById(uid).get()
|
||||||
val project = projectRepository.findById(id).get()
|
val project = projectRepository.findById(id).get()
|
||||||
project.members.add(user)
|
project.members.add(user)
|
||||||
|
user.projects.add(project)
|
||||||
projectRepository.save(project)
|
projectRepository.save(project)
|
||||||
|
return "redirect:/project/$id"
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/removeuser")
|
@PostMapping("/removeuser")
|
||||||
@PreAuthorize("hasPermission(#id, 'Long', '')")
|
@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()
|
val project = projectRepository.findById(id).get()
|
||||||
// Don't allow projects to have no members
|
// Don't allow projects to have no members
|
||||||
if(project.members.size == 1) return "redirect:/project/$id"
|
if(project.members.size == 1) return "redirect:/project/$id"
|
||||||
|
@ -2,10 +2,6 @@ package uk.co.neviyn.projectplanner
|
|||||||
|
|
||||||
import java.time.LocalDateTime
|
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 DisplayUser(val id: Long, val username: String, val email: String, val password: String, val oldPassword: String)
|
||||||
|
|
||||||
data class NewProject(val title: String)
|
data class NewProject(val title: String)
|
||||||
|
@ -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>
|
|
@ -4,8 +4,9 @@
|
|||||||
<title th:text="${project.title} + ' | Project Planner'">Project Planner</title>
|
<title th:text="${project.title} + ' | Project Planner'">Project Planner</title>
|
||||||
</head>
|
</head>
|
||||||
<head>
|
<head>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css" rel="stylesheet" crossorigin="anonymous">
|
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css" rel="stylesheet">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.js" crossorigin="anonymous"></script>
|
<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>
|
<script>
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
let calendarEl = document.getElementById('calendar');
|
let calendarEl = document.getElementById('calendar');
|
||||||
@ -25,6 +26,14 @@
|
|||||||
calendar.render();
|
calendar.render();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
window.onload = function () {
|
||||||
|
const options = {
|
||||||
|
valueNames: ['username'],
|
||||||
|
};
|
||||||
|
new List('user-list', options);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -38,7 +47,9 @@
|
|||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<div class="list-group mb-3">
|
<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>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
<div class="list-group-item active">Members:</div>
|
<div class="list-group-item active">Members:</div>
|
||||||
@ -46,32 +57,37 @@
|
|||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||||
<p th:text="${member.username}">username</p>
|
<p th:text="${member.username}">username</p>
|
||||||
<form class="form-floating mb-3" th:action="@{/project/{pid}/removeuser(pid=${id})}" method="post">
|
<form class="form-floating mb-3" method="post"
|
||||||
<input type="hidden" name="id" th:value="${member.id}">
|
th:action="@{/project/{pid}/removeuser(pid=${id})}">
|
||||||
<button class="btn btn-outline-danger btn-sm" type="submit"><i class="bi bi-x-circle text-danger"></i></button>
|
<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>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<div class="col-10">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Modal for creating new events -->
|
||||||
<div id="newEventModal" class="modal" tabindex="-1">
|
<div class="modal" id="newEventModal" tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">New Event</h5>
|
<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>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-floating mb-3">
|
<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>
|
<label for="titleInput">Event Title</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3">
|
<div class="form-floating mb-3">
|
||||||
@ -79,17 +95,42 @@
|
|||||||
<label for="descriptionInput">Event Description</label>
|
<label for="descriptionInput">Event Description</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3">
|
<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>
|
<label for="startTimeInput">Start Time</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3">
|
<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>
|
<label for="endTimeInput">End Time</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
||||||
<button type="button" class="btn btn-primary">Add Event</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user