Add blocked rooms
This commit is contained in:
parent
4aeb97a79e
commit
d8c770054d
|
@ -40,6 +40,17 @@ fun checkConstraints(
|
|||
errors += ConstraintError("Work group requires accessible, but room does not have one!")
|
||||
}
|
||||
|
||||
val blocked = schedule.room.blocked.map {
|
||||
it.checkBlock(
|
||||
schedule.day,
|
||||
schedule.time,
|
||||
schedule.time + schedule.workGroup.length
|
||||
)
|
||||
}.any {it}
|
||||
if (blocked) {
|
||||
errors += ConstraintError("The room ${schedule.room.name} is blocked!")
|
||||
}
|
||||
|
||||
val start = schedule.getAbsoluteStartTime()
|
||||
val end = schedule.getAbsoluteEndTime()
|
||||
|
||||
|
@ -71,7 +82,7 @@ fun checkConstraints(
|
|||
when (type) {
|
||||
ConstraintType.OnlyOnDay -> {
|
||||
val onlyOnDay = constraints.map { it.day == schedule.day }
|
||||
if (onlyOnDay.none()) {
|
||||
if (onlyOnDay.none { it }) {
|
||||
val dayList = constraints.mapNotNull { it.day }.distinct().sorted()
|
||||
errors += ConstraintError("Work group requires days $dayList, but is on ${schedule.day}!")
|
||||
}
|
||||
|
@ -79,7 +90,7 @@ fun checkConstraints(
|
|||
|
||||
ConstraintType.NotOnDay -> {
|
||||
val notOnDay = constraints.map { it.day != schedule.day }
|
||||
if (notOnDay.none()) {
|
||||
if (notOnDay.none { it }) {
|
||||
val dayList = constraints.mapNotNull { it.day }.distinct().sorted()
|
||||
errors += ConstraintError("Work group requires not days $dayList, but is on ${schedule.day}!")
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import kotlin.random.Random
|
|||
@Serializable
|
||||
data class Post(
|
||||
override val id: Long? = null,
|
||||
val name: String,
|
||||
val content: String,
|
||||
val url: String,
|
||||
val image: String?,
|
||||
val pinned: Boolean,
|
||||
val hideOnProjector: Boolean,
|
||||
val name: String = "",
|
||||
val content: String = "",
|
||||
val url: String = "",
|
||||
val image: String? = null,
|
||||
val pinned: Boolean = false,
|
||||
val hideOnProjector: Boolean = false,
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
|
|
@ -6,20 +6,19 @@ import kotlinx.serialization.Serializable
|
|||
@Serializable
|
||||
data class Room(
|
||||
override val id: Long? = null,
|
||||
val name: String,
|
||||
val places: Int,
|
||||
val projector: Boolean,
|
||||
val internet: Boolean,
|
||||
val whiteboard: Boolean,
|
||||
val blackboard: Boolean,
|
||||
val accessible: Boolean,
|
||||
val pool: Boolean,
|
||||
val name: String = "",
|
||||
val places: Int = 0,
|
||||
val projector: Boolean = false,
|
||||
val internet: Boolean = false,
|
||||
val whiteboard: Boolean = false,
|
||||
val blackboard: Boolean = false,
|
||||
val accessible: Boolean = false,
|
||||
val pool: Boolean = false,
|
||||
val blocked : List<RoomBlock> = emptyList(),
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
||||
|
||||
|
||||
override fun createSearch() = SearchElement(
|
||||
mapOf(
|
||||
"name" to name
|
||||
|
@ -50,6 +49,7 @@ data class Room(
|
|||
if (blackboard != other.blackboard) return false
|
||||
if (accessible != other.accessible) return false
|
||||
if (pool != other.pool) return false
|
||||
if (blocked != other.blocked) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ data class Room(
|
|||
result = 31 * result + blackboard.hashCode()
|
||||
result = 31 * result + accessible.hashCode()
|
||||
result = 31 * result + pool.hashCode()
|
||||
result = 31 * result + blocked.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
19
src/commonMain/kotlin/de/kif/common/model/RoomBlock.kt
Normal file
19
src/commonMain/kotlin/de/kif/common/model/RoomBlock.kt
Normal file
|
@ -0,0 +1,19 @@
|
|||
package de.kif.common.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class RoomBlock(
|
||||
val day: Int,
|
||||
val start: Int? = null,
|
||||
val end: Int? = null
|
||||
) {
|
||||
fun checkBlock(day: Int, start: Int, end: Int): Boolean {
|
||||
if (this.day != day) return false
|
||||
|
||||
val s = this.start ?: Int.MIN_VALUE
|
||||
val e = this.end ?: Int.MAX_VALUE
|
||||
|
||||
return s <= end && start < e
|
||||
}
|
||||
}
|
|
@ -10,8 +10,8 @@ data class Schedule(
|
|||
val room: Room,
|
||||
val day: Int,
|
||||
val time: Int,
|
||||
val lockRoom: Boolean,
|
||||
val lockTime: Boolean,
|
||||
val lockRoom: Boolean = false,
|
||||
val lockTime: Boolean = false,
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
|
|
@ -5,9 +5,9 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable
|
||||
data class Track(
|
||||
override val id: Long?,
|
||||
val name: String,
|
||||
val color: Color,
|
||||
override val id: Long? = null,
|
||||
val name: String = "",
|
||||
val color: Color = Color.WHITE,
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
|
|
@ -5,10 +5,10 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable
|
||||
data class User(
|
||||
override val id: Long?,
|
||||
val username: String,
|
||||
val password: String,
|
||||
val permissions: Set<Permission>,
|
||||
override val id: Long? = null,
|
||||
val username: String = "",
|
||||
val password: String = "",
|
||||
val permissions: Set<Permission> = emptySet(),
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
|
|
@ -5,21 +5,21 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable
|
||||
data class WorkGroup(
|
||||
override val id: Long?,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val interested: Int,
|
||||
val track: Track?,
|
||||
val projector: Boolean,
|
||||
val resolution: Boolean,
|
||||
val internet: Boolean,
|
||||
val whiteboard: Boolean,
|
||||
val blackboard: Boolean,
|
||||
val accessible: Boolean,
|
||||
val length: Int,
|
||||
val language: Language,
|
||||
val leader: List<String>,
|
||||
val constraints: List<Constraint>,
|
||||
override val id: Long? = null,
|
||||
val name: String = "",
|
||||
val description: String = "",
|
||||
val interested: Int = 0,
|
||||
val track: Track? = null,
|
||||
val projector: Boolean = false,
|
||||
val resolution: Boolean = false,
|
||||
val internet: Boolean = false,
|
||||
val whiteboard: Boolean = false,
|
||||
val blackboard: Boolean = false,
|
||||
val accessible: Boolean = false,
|
||||
val length: Int = 0,
|
||||
val language: Language = Language.GERMAN,
|
||||
val leader: List<String> = emptyList(),
|
||||
val constraints: List<WorkGroupConstraint> = emptyList(),
|
||||
override val createdAt: Long = 0,
|
||||
override val updateAt: Long = 0
|
||||
) : Model {
|
||||
|
|
|
@ -3,7 +3,7 @@ package de.kif.common.model
|
|||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Constraint(
|
||||
data class WorkGroupConstraint(
|
||||
val type: ConstraintType,
|
||||
val day: Int? = null,
|
||||
val time: Int? = null,
|
|
@ -22,6 +22,7 @@ class PushServiceClient {
|
|||
private var timestamp = body.dataset["timestamp"]?.toLongOrNull() ?: 0L
|
||||
private val signature = body.dataset["signature"] ?: ""
|
||||
private var intervalId: Int? = null
|
||||
private var errorTimeout = ERROR_TIMEOUT
|
||||
|
||||
private fun reload() {
|
||||
val id = intervalId ?: return
|
||||
|
@ -33,6 +34,7 @@ class PushServiceClient {
|
|||
|
||||
private fun onMessage(messageBox: MessageBox) {
|
||||
body.classList.remove("offline")
|
||||
errorTimeout = ERROR_TIMEOUT
|
||||
|
||||
if (messageBox.valid && signature == messageBox.signature) {
|
||||
timestamp = messageBox.timestamp
|
||||
|
@ -54,6 +56,11 @@ class PushServiceClient {
|
|||
}
|
||||
|
||||
private fun onError(code: Int) {
|
||||
if (errorTimeout > 0) {
|
||||
errorTimeout--
|
||||
return
|
||||
}
|
||||
|
||||
if (!body.classList.contains("offline")) {
|
||||
console.log("Offline reason: $code")
|
||||
}
|
||||
|
@ -105,6 +112,10 @@ class PushServiceClient {
|
|||
request()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ERROR_TIMEOUT = 2
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MessageHandler(val repository: RepositoryType) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package de.kif.frontend
|
|||
import de.kif.frontend.views.board.initBoard
|
||||
import de.kif.frontend.views.calendar.initCalendar
|
||||
import de.kif.frontend.views.initAnnouncement
|
||||
import de.kif.frontend.views.initRoomConstraints
|
||||
import de.kif.frontend.views.initWorkGroupConstraints
|
||||
import de.kif.frontend.views.overview.initOverviewMain
|
||||
import de.kif.frontend.views.overview.initPostEdit
|
||||
|
@ -23,6 +24,9 @@ fun main() = init {
|
|||
if (document.getElementsByClassName("work-group-constraints").length > 0) {
|
||||
initWorkGroupConstraints()
|
||||
}
|
||||
if (document.getElementsByClassName("room-constraints").length > 0) {
|
||||
initRoomConstraints()
|
||||
}
|
||||
if (document.getElementsByClassName("overview-main").length > 0) {
|
||||
initOverviewMain()
|
||||
}
|
||||
|
|
57
src/jsMain/kotlin/de/kif/frontend/views/RoomConstraints.kt
Normal file
57
src/jsMain/kotlin/de/kif/frontend/views/RoomConstraints.kt
Normal file
|
@ -0,0 +1,57 @@
|
|||
package de.kif.frontend.views
|
||||
|
||||
import de.westermann.kwebview.View
|
||||
import de.westermann.kwebview.components.InputType
|
||||
import de.westermann.kwebview.components.InputView
|
||||
import de.westermann.kwebview.components.TextView
|
||||
import de.westermann.kwebview.createHtmlView
|
||||
import de.westermann.kwebview.iterator
|
||||
import org.w3c.dom.HTMLDivElement
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.get
|
||||
import kotlin.browser.document
|
||||
|
||||
fun initRoomConstraints() {
|
||||
var index = 10000
|
||||
|
||||
val constraints =
|
||||
document.getElementsByClassName("room-constraints")[0] as HTMLElement
|
||||
val addButton =
|
||||
View.wrap(document.getElementsByClassName("room-constraints-add")[0] as HTMLElement)
|
||||
|
||||
addButton.onClick {
|
||||
constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) {
|
||||
classList += "input-group"
|
||||
html.appendChild(TextView("Gesperrt").apply {
|
||||
classList += "form-btn"
|
||||
onClick { this@wrap.html.remove() }
|
||||
}.html)
|
||||
html.appendChild(InputView(InputType.TEXT).apply {
|
||||
classList += "form-control"
|
||||
html.name = "constraint-room-day-${index}"
|
||||
placeholder = "Tag"
|
||||
}.html)
|
||||
html.appendChild(InputView(InputType.TEXT).apply {
|
||||
classList += "form-control"
|
||||
html.name = "constraint-room-start-${index}"
|
||||
placeholder = "Start"
|
||||
}.html)
|
||||
html.appendChild(InputView(InputType.TEXT).apply {
|
||||
classList += "form-control"
|
||||
html.name = "constraint-room-end-${index++}"
|
||||
placeholder = "Ende"
|
||||
}.html)
|
||||
}.html)
|
||||
}
|
||||
|
||||
for (child in constraints.children.iterator()) {
|
||||
if (child.classList.contains("input-group")) {
|
||||
val span = child.firstElementChild as HTMLElement
|
||||
|
||||
span.addEventListener("click", org.w3c.dom.events.EventListener {
|
||||
println("click")
|
||||
child.remove()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,12 +83,10 @@ fun initWorkGroupConstraints() {
|
|||
html.name = "constraint-only-before-time-day-${index}"
|
||||
placeholder = "Tag (optional)"
|
||||
}.html)
|
||||
html.appendChild(InputView(InputType.NUMBER).apply {
|
||||
html.appendChild(InputView(InputType.TEXT).apply {
|
||||
classList += "form-control"
|
||||
html.name = "constraint-only-before-time-${index++}"
|
||||
min = -1337.0
|
||||
max = 133700.0
|
||||
placeholder = "Minuten"
|
||||
placeholder = "HH:MM | Min"
|
||||
}.html)
|
||||
}.html)
|
||||
}
|
||||
|
@ -106,12 +104,10 @@ fun initWorkGroupConstraints() {
|
|||
html.name = "constraint-only-after-time-day-${index}"
|
||||
placeholder = "Tag (optional)"
|
||||
}.html)
|
||||
html.appendChild(InputView(InputType.NUMBER).apply {
|
||||
html.appendChild(InputView(InputType.TEXT).apply {
|
||||
classList += "form-control"
|
||||
html.name = "constraint-only-after-time-${index++}"
|
||||
min = -1337.0
|
||||
max = 133700.0
|
||||
placeholder = "Minuten"
|
||||
placeholder = "HH:MM | Min"
|
||||
}.html)
|
||||
}.html)
|
||||
}
|
||||
|
@ -174,10 +170,8 @@ fun initWorkGroupConstraints() {
|
|||
}
|
||||
|
||||
for (child in constraints.children.iterator()) {
|
||||
console.log(child)
|
||||
if (child.classList.contains("input-group")) {
|
||||
val span = child.firstElementChild as HTMLElement
|
||||
console.log(span)
|
||||
|
||||
span.addEventListener("click", org.w3c.dom.events.EventListener {
|
||||
println("click")
|
||||
|
|
|
@ -161,6 +161,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.calendar-cell[data-blocked = "true"] {
|
||||
background-color: var(--table-header-color) !important;
|
||||
}
|
||||
|
||||
.calendar-tools {
|
||||
position: absolute;
|
||||
top: -5rem;
|
||||
|
|
|
@ -160,4 +160,48 @@
|
|||
position: absolute !important;
|
||||
top: 0.6rem;
|
||||
left: 6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.room-constraints {
|
||||
position: relative;
|
||||
|
||||
& > label {
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
span {
|
||||
width: 8rem;
|
||||
flex-basis: 8rem;
|
||||
flex-grow: 0;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover::after {
|
||||
content: 'LÖSCHEN';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
font-weight: bold;
|
||||
color: var(--primary-text-color);
|
||||
background: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
width: 12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.room-constraints-add {
|
||||
position: absolute;
|
||||
top: -0.5rem;
|
||||
right: 0;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,14 @@ import io.ktor.jackson.jackson
|
|||
import io.ktor.response.respond
|
||||
import io.ktor.routing.route
|
||||
import io.ktor.routing.routing
|
||||
import mu.KotlinLogging
|
||||
import org.slf4j.event.Level
|
||||
import java.nio.file.Paths
|
||||
|
||||
val prefix = Configuration.Server.prefix
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
fun Application.main() {
|
||||
install(DefaultHeaders)
|
||||
install(CallLogging) {
|
||||
|
@ -96,4 +99,6 @@ fun Application.main() {
|
|||
pushService()
|
||||
}
|
||||
}
|
||||
|
||||
logger.info { "Responding at http://${Configuration.Server.host}:${Configuration.Server.port}$prefix/" }
|
||||
}
|
||||
|
|
|
@ -53,4 +53,5 @@ fun main(args: Array<String>) {
|
|||
host = Configuration.Server.host,
|
||||
module = Application::main
|
||||
).start(wait = true)
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ object DbRoom : Table() {
|
|||
val accessible = bool("accessible")
|
||||
val pool = bool("pool").default(false)
|
||||
|
||||
val blocked = text("blocked").default("[]")
|
||||
|
||||
val createdAt = long("createdAt")
|
||||
val updatedAt = long("updatedAt")
|
||||
}
|
||||
|
|
|
@ -6,9 +6,12 @@ import de.kif.backend.util.PushService
|
|||
import de.kif.common.MessageType
|
||||
import de.kif.common.Repository
|
||||
import de.kif.common.RepositoryType
|
||||
import de.kif.common.Serialization
|
||||
import de.kif.common.model.Room
|
||||
import de.kif.common.model.RoomBlock
|
||||
import de.westermann.kobserve.event.EventHandler
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.list
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import java.util.Date
|
||||
|
||||
|
@ -28,6 +31,7 @@ object RoomRepository : Repository<Room> {
|
|||
val blackboard = row[DbRoom.blackboard]
|
||||
val accessible = row[DbRoom.accessible]
|
||||
val pool = row[DbRoom.pool]
|
||||
val blocked = Serialization.parse(RoomBlock.serializer().list, row[DbRoom.blocked])
|
||||
|
||||
val createdAt = row[DbRoom.createdAt]
|
||||
val updatedAt = row[DbRoom.updatedAt]
|
||||
|
@ -42,6 +46,7 @@ object RoomRepository : Repository<Room> {
|
|||
blackboard,
|
||||
accessible,
|
||||
pool,
|
||||
blocked,
|
||||
createdAt,
|
||||
updatedAt
|
||||
)
|
||||
|
@ -66,6 +71,7 @@ object RoomRepository : Repository<Room> {
|
|||
it[blackboard] = model.blackboard
|
||||
it[accessible] = model.accessible
|
||||
it[pool] = model.pool
|
||||
it[blocked] = Serialization.stringify(RoomBlock.serializer().list, model.blocked)
|
||||
it[createdAt] = now
|
||||
it[updatedAt] = now
|
||||
}[DbRoom.id] ?: throw IllegalStateException("Cannot create model!")
|
||||
|
@ -91,6 +97,7 @@ object RoomRepository : Repository<Room> {
|
|||
it[blackboard] = model.blackboard
|
||||
it[accessible] = model.accessible
|
||||
it[pool] = model.pool
|
||||
it[blocked] = Serialization.stringify(RoomBlock.serializer().list, model.blocked)
|
||||
it[updatedAt] = now
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import de.kif.common.MessageType
|
|||
import de.kif.common.Repository
|
||||
import de.kif.common.RepositoryType
|
||||
import de.kif.common.Serialization
|
||||
import de.kif.common.model.Constraint
|
||||
import de.kif.common.model.WorkGroupConstraint
|
||||
import de.kif.common.model.WorkGroup
|
||||
import de.westermann.kobserve.event.EventHandler
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -37,7 +37,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
|
|||
val length = row[DbWorkGroup.length]
|
||||
val language = row[DbWorkGroup.language]
|
||||
val leader = Serialization.parse(String.serializer().list, row[DbWorkGroup.leader])
|
||||
val constraints = Serialization.parse(Constraint.serializer().list, row[DbWorkGroup.constraints])
|
||||
val constraints = Serialization.parse(WorkGroupConstraint.serializer().list, row[DbWorkGroup.constraints])
|
||||
|
||||
val createdAt = row[DbWorkGroup.createdAt]
|
||||
val updatedAt = row[DbWorkGroup.updatedAt]
|
||||
|
@ -93,7 +93,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
|
|||
it[length] = model.length
|
||||
it[language] = model.language
|
||||
it[leader] = Serialization.stringify(String.serializer().list, model.leader)
|
||||
it[constraints] = Serialization.stringify(Constraint.serializer().list, model.constraints)
|
||||
it[constraints] = Serialization.stringify(WorkGroupConstraint.serializer().list, model.constraints)
|
||||
|
||||
it[createdAt] = now
|
||||
it[updatedAt] = now
|
||||
|
@ -125,7 +125,7 @@ object WorkGroupRepository : Repository<WorkGroup> {
|
|||
it[length] = model.length
|
||||
it[language] = model.language
|
||||
it[leader] = Serialization.stringify(String.serializer().list, model.leader)
|
||||
it[constraints] = Serialization.stringify(Constraint.serializer().list, model.constraints)
|
||||
it[constraints] = Serialization.stringify(WorkGroupConstraint.serializer().list, model.constraints)
|
||||
|
||||
it[updatedAt] = now
|
||||
}
|
||||
|
|
|
@ -135,8 +135,11 @@ fun DIV.renderCalendar(
|
|||
}
|
||||
|
||||
for (room in rooms) {
|
||||
val blocked = room.blocked.map { it.checkBlock(day, start, end) }.any { it }
|
||||
|
||||
div("calendar-cell") {
|
||||
attributes["data-room"] = room.id.toString()
|
||||
attributes["data-blocked"] = blocked.toString()
|
||||
|
||||
title = room.name + " - " + timeString
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import de.kif.backend.view.respondMain
|
|||
import de.kif.common.Search
|
||||
import de.kif.common.model.Permission
|
||||
import de.kif.common.model.Room
|
||||
import de.kif.common.model.RoomBlock
|
||||
import io.ktor.application.call
|
||||
import io.ktor.html.insert
|
||||
import io.ktor.request.receiveParameters
|
||||
|
@ -235,6 +236,68 @@ fun Route.room() {
|
|||
}
|
||||
}
|
||||
|
||||
div("form-group room-constraints") {
|
||||
label {
|
||||
+"Sperrzeiten"
|
||||
}
|
||||
span("form-btn room-constraints-add") {
|
||||
i("material-icons") { +"add" }
|
||||
}
|
||||
|
||||
|
||||
for ((index, constraint) in editRoom.blocked.withIndex()) {
|
||||
div("input-group") {
|
||||
span("form-btn") {
|
||||
+"Gesperrt"
|
||||
}
|
||||
input(
|
||||
name = "constraint-blocked-day-$index",
|
||||
classes = "form-control"
|
||||
) {
|
||||
value = constraint.day.toString()
|
||||
|
||||
placeholder = "Tag"
|
||||
}
|
||||
input(
|
||||
name = "constraint-blocked-start-$index",
|
||||
classes = "form-control"
|
||||
) {
|
||||
val time = constraint.start
|
||||
value = if (time != null) {
|
||||
if (time < 0 || time > 24 * 60) {
|
||||
time.toString()
|
||||
} else {
|
||||
(time / 60).toString().padStart(
|
||||
2,
|
||||
'0'
|
||||
) + ":" + (time % 60).toString().padStart(2, '0')
|
||||
}
|
||||
} else ""
|
||||
|
||||
placeholder = "Start"
|
||||
}
|
||||
input(
|
||||
name = "constraint-blocked-end-$index",
|
||||
classes = "form-control"
|
||||
) {
|
||||
val time = constraint.end
|
||||
value = if (time != null) {
|
||||
if (time < 0 || time > 24 * 60) {
|
||||
time.toString()
|
||||
} else {
|
||||
(time / 60).toString().padStart(
|
||||
2,
|
||||
'0'
|
||||
) + ":" + (time % 60).toString().padStart(2, '0')
|
||||
}
|
||||
} else ""
|
||||
|
||||
placeholder = "Ende"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div("form-group") {
|
||||
a("$prefix/room") {
|
||||
button(classes = "form-btn") {
|
||||
|
@ -273,6 +336,9 @@ fun Route.room() {
|
|||
params["accessible"]?.let { room = room.copy(accessible = it == "on") }
|
||||
params["pool"]?.let { room = room.copy(pool = it == "on") }
|
||||
|
||||
val blocked = parseConstraintParam(params)
|
||||
room = room.copy(blocked = blocked)
|
||||
|
||||
RoomRepository.update(room)
|
||||
|
||||
call.respondRedirect("$prefix/rooms")
|
||||
|
@ -410,6 +476,15 @@ fun Route.room() {
|
|||
}
|
||||
}
|
||||
|
||||
div("form-group room-constraints") {
|
||||
label {
|
||||
+"Sperrzeiten"
|
||||
}
|
||||
span("form-btn room-constraints-add") {
|
||||
i("material-icons") { +"add" }
|
||||
}
|
||||
}
|
||||
|
||||
div("form-group") {
|
||||
a("$prefix/room") {
|
||||
button(classes = "form-btn") {
|
||||
|
@ -441,7 +516,9 @@ fun Route.room() {
|
|||
val accessible = params["accessible"] == "on"
|
||||
val pool = params["pool"] == "on"
|
||||
|
||||
val room = Room(null, name, places, projector, internet, whiteboard, blackboard, accessible, pool)
|
||||
val blocked = parseConstraintParam(params)
|
||||
|
||||
val room = Room(null, name, places, projector, internet, whiteboard, blackboard, accessible, pool, blocked)
|
||||
|
||||
RoomRepository.create(room)
|
||||
|
||||
|
@ -459,3 +536,47 @@ fun Route.room() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseConstraintParam(params: Map<String, String?>): List<RoomBlock> {
|
||||
val blocks = mutableMapOf<Int, RoomBlock>()
|
||||
|
||||
for ((key, value) in params) {
|
||||
if (key.startsWith("constraint-room")) {
|
||||
val id = key.substringAfterLast("-").toIntOrNull() ?: -1
|
||||
|
||||
var entry = blocks[id] ?: RoomBlock(0)
|
||||
|
||||
when {
|
||||
"day" in key -> entry = entry.copy(day = value?.toIntOrNull() ?: 0)
|
||||
"start" in key -> {
|
||||
val v = value ?: ""
|
||||
val h = v.substringBefore(":").toIntOrNull()
|
||||
val m = v.substringAfter(":").toIntOrNull()
|
||||
|
||||
val time = if (h != null && m != null) {
|
||||
h * 60 + m
|
||||
} else {
|
||||
v.toIntOrNull()
|
||||
}
|
||||
entry = entry.copy(start = time)
|
||||
}
|
||||
"end" in key -> {
|
||||
val v = value ?: ""
|
||||
val h = v.substringBefore(":").toIntOrNull()
|
||||
val m = v.substringAfter(":").toIntOrNull()
|
||||
|
||||
val time = if (h != null && m != null) {
|
||||
h * 60 + m
|
||||
} else {
|
||||
v.toIntOrNull()
|
||||
}
|
||||
entry = entry.copy(end = time)
|
||||
}
|
||||
}
|
||||
|
||||
blocks[id] = entry
|
||||
}
|
||||
}
|
||||
|
||||
return blocks.values.toList()
|
||||
}
|
||||
|
|
|
@ -436,15 +436,19 @@ fun Route.workGroup() {
|
|||
}
|
||||
input(
|
||||
name = "constraint-only-before-time-$index",
|
||||
classes = "form-control",
|
||||
type = InputType.number
|
||||
classes = "form-control"
|
||||
) {
|
||||
value = constraint.time.toString()
|
||||
val time = constraint.time ?: 0
|
||||
value = if (time < 0 || time > 24 * 60) {
|
||||
time.toString()
|
||||
} else {
|
||||
(time / 60).toString().padStart(
|
||||
2,
|
||||
'0'
|
||||
) + ":" + (time % 60).toString().padStart(2, '0')
|
||||
}
|
||||
|
||||
min = "-1337"
|
||||
max = "133700"
|
||||
|
||||
placeholder = "Minuten"
|
||||
placeholder = "HH:MM | Min"
|
||||
}
|
||||
}
|
||||
ConstraintType.OnlyAfterTime -> {
|
||||
|
@ -461,15 +465,19 @@ fun Route.workGroup() {
|
|||
}
|
||||
input(
|
||||
name = "constraint-only-after-time-$index",
|
||||
classes = "form-control",
|
||||
type = InputType.number
|
||||
classes = "form-control"
|
||||
) {
|
||||
value = constraint.time.toString()
|
||||
val time = constraint.time ?: 0
|
||||
value = if (time < 0 || time > 24 * 60) {
|
||||
time.toString()
|
||||
} else {
|
||||
(time / 60).toString().padStart(
|
||||
2,
|
||||
'0'
|
||||
) + ":" + (time % 60).toString().padStart(2, '0')
|
||||
}
|
||||
|
||||
min = "-1337"
|
||||
max = "133700"
|
||||
|
||||
placeholder = "Minuten"
|
||||
placeholder = "HH:MM | Min"
|
||||
}
|
||||
}
|
||||
ConstraintType.NotAtSameTime -> {
|
||||
|
@ -886,30 +894,50 @@ private fun parseConstraintParam(params: Map<String, String?>) = params.map { (k
|
|||
val id = key.substringAfterLast("-").toIntOrNull() ?: -1
|
||||
id to when {
|
||||
key.startsWith("constraint-only-on-day") -> {
|
||||
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyOnDay, day = it) }
|
||||
value?.toIntOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyOnDay, day = it) }
|
||||
}
|
||||
key.startsWith("constraint-not-on-day") -> {
|
||||
value?.toIntOrNull()?.let { Constraint(ConstraintType.NotOnDay, day = it) }
|
||||
value?.toIntOrNull()?.let { WorkGroupConstraint(ConstraintType.NotOnDay, day = it) }
|
||||
}
|
||||
key.startsWith("constraint-only-after-time") -> {
|
||||
if ("day" in key) {
|
||||
Constraint(ConstraintType.OnlyAfterTime, day = value?.toIntOrNull())
|
||||
WorkGroupConstraint(ConstraintType.OnlyAfterTime, day = value?.toIntOrNull())
|
||||
} else {
|
||||
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyAfterTime, time = it) }
|
||||
val v = value ?: ""
|
||||
if (":" in v) {
|
||||
val h = v.substringBefore(":").toIntOrNull()
|
||||
val m = v.substringAfter(":").toIntOrNull()
|
||||
|
||||
if (h != null && m != null) {
|
||||
WorkGroupConstraint(ConstraintType.OnlyAfterTime, time = h * 60 + m)
|
||||
} else {
|
||||
v.toIntOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyAfterTime, time = it) }
|
||||
}
|
||||
} else null
|
||||
}
|
||||
}
|
||||
key.startsWith("constraint-only-before-time") -> {
|
||||
if ("day" in key) {
|
||||
Constraint(ConstraintType.OnlyBeforeTime, day = value?.toIntOrNull())
|
||||
WorkGroupConstraint(ConstraintType.OnlyBeforeTime, day = value?.toIntOrNull())
|
||||
} else {
|
||||
value?.toIntOrNull()?.let { Constraint(ConstraintType.OnlyBeforeTime, time = it) }
|
||||
val v = value ?: ""
|
||||
if (":" in v) {
|
||||
val h = v.substringBefore(":").toIntOrNull()
|
||||
val m = v.substringAfter(":").toIntOrNull()
|
||||
|
||||
if (h != null && m != null) {
|
||||
WorkGroupConstraint(ConstraintType.OnlyBeforeTime, time = h * 60 + m)
|
||||
} else {
|
||||
v.toIntOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyBeforeTime, time = it) }
|
||||
}
|
||||
} else null
|
||||
}
|
||||
}
|
||||
key.startsWith("constraint-not-at-same-time") -> {
|
||||
value?.toLongOrNull()?.let { Constraint(ConstraintType.NotAtSameTime, workGroup = it) }
|
||||
value?.toLongOrNull()?.let { WorkGroupConstraint(ConstraintType.NotAtSameTime, workGroup = it) }
|
||||
}
|
||||
key.startsWith("constraint-only-after-work-group") -> {
|
||||
value?.toLongOrNull()?.let { Constraint(ConstraintType.OnlyAfterWorkGroup, workGroup = it) }
|
||||
value?.toLongOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyAfterWorkGroup, workGroup = it) }
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
@ -925,12 +953,12 @@ private fun parseConstraintParam(params: Map<String, String?>) = params.map { (k
|
|||
|
||||
when {
|
||||
c1.type != c2.type -> null
|
||||
c1.type == ConstraintType.OnlyBeforeTime -> Constraint(
|
||||
c1.type == ConstraintType.OnlyBeforeTime -> WorkGroupConstraint(
|
||||
ConstraintType.OnlyBeforeTime,
|
||||
day = c1.day ?: c2.day,
|
||||
time = c1.time ?: c2.time
|
||||
)
|
||||
c1.type == ConstraintType.OnlyAfterTime -> Constraint(
|
||||
c1.type == ConstraintType.OnlyAfterTime -> WorkGroupConstraint(
|
||||
ConstraintType.OnlyAfterTime,
|
||||
day = c1.day ?: c2.day,
|
||||
time = c1.time ?: c2.time
|
||||
|
|
|
@ -9,7 +9,7 @@ class LogbackFilter : Filter<ILoggingEvent>() {
|
|||
override fun decide(event: ILoggingEvent?): FilterReply = if (event == null) {
|
||||
FilterReply.NEUTRAL
|
||||
} else {
|
||||
if (event.loggerName.contains("Exposed".toRegex())) {
|
||||
if (event.loggerName.contains("Exposed|ktor.application".toRegex())) {
|
||||
if (event.level.toInt() > Level.ERROR_INT) FilterReply.ACCEPT else FilterReply.DENY
|
||||
} else {
|
||||
FilterReply.ACCEPT
|
||||
|
|
Loading…
Reference in a new issue