Add blocked rooms

This commit is contained in:
Lars Westermann 2019-06-12 12:18:29 +02:00
parent 4aeb97a79e
commit d8c770054d
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
24 changed files with 396 additions and 84 deletions

View file

@ -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}!")
}

View file

@ -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 {

View file

@ -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
}
}

View 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
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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,

View file

@ -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) {

View file

@ -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()
}

View 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()
})
}
}
}

View file

@ -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")

View file

@ -161,6 +161,10 @@
}
}
.calendar-cell[data-blocked = "true"] {
background-color: var(--table-header-color) !important;
}
.calendar-tools {
position: absolute;
top: -5rem;

View file

@ -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;
}

View file

@ -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/" }
}

View file

@ -53,4 +53,5 @@ fun main(args: Array<String>) {
host = Configuration.Server.host,
module = Application::main
).start(wait = true)
}

View file

@ -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")
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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()
}

View file

@ -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

View file

@ -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