Events can now be dragged and dropped

This commit is contained in:
neviyn 2021-03-31 21:36:15 +01:00
parent 570151a5ec
commit d912144625
5 changed files with 46 additions and 23 deletions

View File

@ -1,8 +1,10 @@
package uk.co.neviyn.projectplanner package uk.co.neviyn.projectplanner
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import java.time.Instant
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.persistence.CascadeType import javax.persistence.CascadeType
import javax.persistence.Column
import javax.persistence.Entity import javax.persistence.Entity
import javax.persistence.GeneratedValue import javax.persistence.GeneratedValue
import javax.persistence.GenerationType import javax.persistence.GenerationType
@ -56,8 +58,10 @@ class Project(
class Event( class Event(
var title: String = "INVALID", var title: String = "INVALID",
var description: String = "INVALID", var description: String = "INVALID",
var start: LocalDateTime = LocalDateTime.MIN, @Column(name = "start_time")
var end: LocalDateTime = LocalDateTime.MIN, var start: Instant = Instant.MIN,
@Column(name = "end_time")
var end: Instant = Instant.MIN,
@ManyToOne @ManyToOne
@JoinColumn(name = "project_id") @JoinColumn(name = "project_id")
@JsonIgnore @JsonIgnore

View File

@ -14,9 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.ResponseBody import org.springframework.web.bind.annotation.ResponseBody
import java.time.Instant import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import javax.persistence.EntityManager import javax.persistence.EntityManager
import javax.transaction.Transactional import javax.transaction.Transactional
@ -110,19 +107,15 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
return "project" return "project"
} }
val f: DateTimeFormatter = DateTimeFormatter.ISO_INSTANT
@GetMapping("/events") @GetMapping("/events")
@PreAuthorize("hasPermission(#id, 'Long', '')") @PreAuthorize("hasPermission(#id, 'Long', '')")
@ResponseBody @ResponseBody
fun getProjectEventsBetween(@PathVariable id: Long, @RequestParam start: String?, @RequestParam end: String?) : Set<Event> { fun getProjectEventsBetween(@PathVariable id: Long, @RequestParam start: Instant?, @RequestParam end: Instant?) : Set<Event> {
val startTime: LocalDateTime? = LocalDateTime.ofInstant(Instant.from(f.parse(start)), ZoneOffset.UTC)
val endTime: LocalDateTime? = LocalDateTime.ofInstant(Instant.from(f.parse(end)), ZoneOffset.UTC)
val project = projectRepository.findById(id).get() val project = projectRepository.findById(id).get()
if(startTime == null && endTime == null) return project.events if(start == null && end == null) return project.events
else if(startTime == null && endTime != null) return eventRepository.findByEndBeforeAndProject(endTime, project) else if(start == null && end != null) return eventRepository.findByEndBeforeAndProject(end, project)
else if(startTime != null && endTime == null) return eventRepository.findByStartAfterAndProject(startTime, project) else if(start != null && end == null) return eventRepository.findByStartAfterAndProject(start, project)
return eventRepository.findByStartAfterAndEndBeforeAndProjectIs(startTime!!, endTime!!, project) return eventRepository.findByStartAfterAndEndBeforeAndProjectIs(start!!, end!!, project)
} }
@ -158,8 +151,14 @@ class ProjectController @Autowired constructor(val projectRepository: ProjectRep
@PostMapping("/editevent") @PostMapping("/editevent")
@PreAuthorize("hasPermission(#id, 'Long', '')") @PreAuthorize("hasPermission(#id, 'Long', '')")
fun editEvent(@PathVariable id: Long) { @ResponseBody
TODO() fun editEvent(@PathVariable id: Long, @RequestBody e: EditedEvent) {
val event = eventRepository.findById(e.id).get()
event.title = e.title
event.description = e.description
event.start = e.start
event.end = e.end
eventRepository.save(event)
} }
@PostMapping("/deleteevent") @PostMapping("/deleteevent")

View File

@ -1,7 +1,7 @@
package uk.co.neviyn.projectplanner package uk.co.neviyn.projectplanner
import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.CrudRepository
import java.time.LocalDateTime import java.time.Instant
interface UserRepository : CrudRepository<User, Long>{ interface UserRepository : CrudRepository<User, Long>{
fun findByUsername(username: String): User? fun findByUsername(username: String): User?
@ -11,9 +11,9 @@ interface UserRepository : CrudRepository<User, Long>{
interface ProjectRepository : CrudRepository<Project, Long>{} interface ProjectRepository : CrudRepository<Project, Long>{}
interface EventRepository : CrudRepository<Event, Long>{ interface EventRepository : CrudRepository<Event, Long>{
fun findByStartAfterAndProject(start: LocalDateTime, project: Project) : Set<Event> fun findByStartAfterAndProject(start: Instant, project: Project) : Set<Event>
fun findByEndBeforeAndProject(end: LocalDateTime, project: Project) : Set<Event> fun findByEndBeforeAndProject(end: Instant, project: Project) : Set<Event>
fun findByStartAfterAndEndBeforeAndProjectIs(start: LocalDateTime, end: LocalDateTime, project: Project) : Set<Event> fun findByStartAfterAndEndBeforeAndProjectIs(start: Instant, end: Instant, project: Project) : Set<Event>
} }
interface TagRepository : CrudRepository<Tag, Long>{} interface TagRepository : CrudRepository<Tag, Long>{}

View File

@ -1,9 +1,11 @@
package uk.co.neviyn.projectplanner package uk.co.neviyn.projectplanner
import java.time.LocalDateTime import java.time.Instant
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)
data class NewEvent(val title: String, val description: String, val start: LocalDateTime, val end: LocalDateTime) data class NewEvent(val title: String, val description: String, val start: Instant, val end: Instant)
data class EditedEvent(val id: Long, val title: String, val description: String, val start: Instant, val end: Instant)

View File

@ -7,7 +7,7 @@
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.6.0/main.min.css" rel="stylesheet"> <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://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 crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js"></script>
<script> <script th:inline="javascript">
window.onload = function () { window.onload = function () {
let calendarEl = document.getElementById('calendar'); let calendarEl = document.getElementById('calendar');
// noinspection JSUnusedGlobalSymbols // noinspection JSUnusedGlobalSymbols
@ -22,6 +22,24 @@
eventAdd(addInfo) { eventAdd(addInfo) {
console.log(addInfo.event) console.log(addInfo.event)
}, },
eventChange(eventInfo) {
console.log(eventInfo)
let myEvent = {
id: eventInfo.event.id,
title: eventInfo.event.title,
description: eventInfo.event.extendedProps.description,
start: eventInfo.event.start,
end: eventInfo.event.end
}
fetch(window.location.origin + window.location.pathname + "/editevent", {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'X-CSRF-TOKEN': /*[[${_csrf.token}]]*/ 'csrf_token'
},
body: JSON.stringify(myEvent)
})
},
events: window.location.origin + window.location.pathname + "/events" events: window.location.origin + window.location.pathname + "/events"
}); });
calendar.render(); calendar.render();