Add reso check and room list
This commit is contained in:
parent
fface0e5ba
commit
94c35b9067
|
@ -9,6 +9,10 @@ reference = "2019-06-12"
|
||||||
offset = 7200000
|
offset = 7200000
|
||||||
wall_start = 1
|
wall_start = 1
|
||||||
|
|
||||||
|
[reso]
|
||||||
|
day = 3
|
||||||
|
time = 900
|
||||||
|
|
||||||
[general]
|
[general]
|
||||||
wiki_url = "https://wiki.kif.rocks/w/index.php?title=KIF470:Arbeitskreise&action=raw"
|
wiki_url = "https://wiki.kif.rocks/w/index.php?title=KIF470:Arbeitskreise&action=raw"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.kif.common
|
package de.kif.common
|
||||||
|
|
||||||
import de.kif.common.model.ConstraintType
|
import de.kif.common.model.ConstraintType
|
||||||
|
import de.kif.common.model.Room
|
||||||
import de.kif.common.model.Schedule
|
import de.kif.common.model.Schedule
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@ -16,10 +17,15 @@ data class ConstraintMap(
|
||||||
|
|
||||||
fun checkConstraints(
|
fun checkConstraints(
|
||||||
check: List<Schedule>,
|
check: List<Schedule>,
|
||||||
against: List<Schedule>
|
against: List<Schedule>,
|
||||||
|
rooms: List<Room>,
|
||||||
|
resoDay: Int,
|
||||||
|
resoTime: Int
|
||||||
): ConstraintMap {
|
): ConstraintMap {
|
||||||
val map = mutableMapOf<Long, List<ConstraintError>>()
|
val map = mutableMapOf<Long, List<ConstraintError>>()
|
||||||
|
|
||||||
|
val roomMap = rooms.associateBy { it.id }
|
||||||
|
|
||||||
for (schedule in check) {
|
for (schedule in check) {
|
||||||
if (schedule.id == null) continue
|
if (schedule.id == null) continue
|
||||||
val errors = mutableListOf<ConstraintError>()
|
val errors = mutableListOf<ConstraintError>()
|
||||||
|
@ -46,7 +52,7 @@ fun checkConstraints(
|
||||||
schedule.time,
|
schedule.time,
|
||||||
schedule.time + schedule.workGroup.length
|
schedule.time + schedule.workGroup.length
|
||||||
)
|
)
|
||||||
}.any {it}
|
}.any { it }
|
||||||
if (blocked) {
|
if (blocked) {
|
||||||
errors += ConstraintError("The room ${schedule.room.name} is blocked!")
|
errors += ConstraintError("The room ${schedule.room.name} is blocked!")
|
||||||
}
|
}
|
||||||
|
@ -54,10 +60,20 @@ fun checkConstraints(
|
||||||
val start = schedule.getAbsoluteStartTime()
|
val start = schedule.getAbsoluteStartTime()
|
||||||
val end = schedule.getAbsoluteEndTime()
|
val end = schedule.getAbsoluteEndTime()
|
||||||
|
|
||||||
|
|
||||||
|
if (schedule.workGroup.resolution) {
|
||||||
|
val resoDeadline = resoDay * 24 * 60 + resoTime
|
||||||
|
|
||||||
|
if (end > resoDeadline) {
|
||||||
|
errors += ConstraintError("The work group is ${end - resoDeadline} minutes after resolution deadline")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (leader in schedule.workGroup.leader) {
|
for (leader in schedule.workGroup.leader) {
|
||||||
for (s in against) {
|
for (s in against) {
|
||||||
if (
|
if (
|
||||||
schedule != s &&
|
schedule != s &&
|
||||||
|
schedule.day == s.day &&
|
||||||
leader in s.workGroup.leader &&
|
leader in s.workGroup.leader &&
|
||||||
start < s.getAbsoluteEndTime() &&
|
start < s.getAbsoluteEndTime() &&
|
||||||
s.getAbsoluteStartTime() < end
|
s.getAbsoluteStartTime() < end
|
||||||
|
@ -70,6 +86,7 @@ fun checkConstraints(
|
||||||
for (s in against) {
|
for (s in against) {
|
||||||
if (
|
if (
|
||||||
schedule != s &&
|
schedule != s &&
|
||||||
|
schedule.day == s.day &&
|
||||||
schedule.room.id == s.room.id &&
|
schedule.room.id == s.room.id &&
|
||||||
start < s.getAbsoluteEndTime() &&
|
start < s.getAbsoluteEndTime() &&
|
||||||
s.getAbsoluteStartTime() < end
|
s.getAbsoluteStartTime() < end
|
||||||
|
@ -146,6 +163,7 @@ fun checkConstraints(
|
||||||
for (s in against) {
|
for (s in against) {
|
||||||
if (
|
if (
|
||||||
s.workGroup.id == constraint.workGroup &&
|
s.workGroup.id == constraint.workGroup &&
|
||||||
|
schedule.day == s.day &&
|
||||||
start <= s.getAbsoluteEndTime() &&
|
start <= s.getAbsoluteEndTime() &&
|
||||||
s.getAbsoluteStartTime() <= end
|
s.getAbsoluteStartTime() <= end
|
||||||
) {
|
) {
|
||||||
|
@ -159,14 +177,25 @@ fun checkConstraints(
|
||||||
for (constraint in constraints) {
|
for (constraint in constraints) {
|
||||||
for (s in against) {
|
for (s in against) {
|
||||||
if (
|
if (
|
||||||
s.workGroup.id == constraint.workGroup &&
|
s.workGroup.id == constraint.workGroup && (
|
||||||
s.getAbsoluteEndTime() > start
|
s.day > schedule.day ||
|
||||||
|
s.day == schedule.day && s.getAbsoluteEndTime() > start
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
errors += ConstraintError("Work group requires after ${s.workGroup.name}!")
|
errors += ConstraintError("Work group requires after ${s.workGroup.name}!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ConstraintType.Room -> {
|
||||||
|
val roomBools = constraints.map { it.room == schedule.room.id }
|
||||||
|
if (roomBools.none { it }) {
|
||||||
|
val roomList = constraints.mapNotNull { it.room }.distinct().sorted().map {
|
||||||
|
"${(roomMap[it]?.name ?: "")}($it)"
|
||||||
|
}
|
||||||
|
errors += ConstraintError("Work group requires rooms $roomList, but is in room ${schedule.room.name}(${schedule.room.id})")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,43 +7,49 @@ data class WorkGroupConstraint(
|
||||||
val type: ConstraintType,
|
val type: ConstraintType,
|
||||||
val day: Int? = null,
|
val day: Int? = null,
|
||||||
val time: Int? = null,
|
val time: Int? = null,
|
||||||
val workGroup: Long? = null
|
val workGroup: Long? = null,
|
||||||
|
val room: Long? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class ConstraintType {
|
enum class ConstraintType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires day, permits time and workGroup.
|
* Requires day, permits time, workGroup and room.
|
||||||
*/
|
*/
|
||||||
OnlyOnDay,
|
OnlyOnDay,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires day, permits time and workGroup.
|
* Requires day, permits time, workGroup and room.
|
||||||
*/
|
*/
|
||||||
NotOnDay,
|
NotOnDay,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires time, optionally allows day, permits workGroup.
|
* Requires time, optionally allows day, permits workGroup and room.
|
||||||
*/
|
*/
|
||||||
OnlyAfterTime,
|
OnlyAfterTime,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires time, optionally allows day, permits workGroup.
|
* Requires time, optionally allows day, permits workGroup and room.
|
||||||
*/
|
*/
|
||||||
OnlyBeforeTime,
|
OnlyBeforeTime,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires time, optionally allows day, permits workGroup
|
* Requires time, optionally allows day, permits workGroup and room.
|
||||||
*/
|
*/
|
||||||
ExactTime,
|
ExactTime,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires workGroup, permits day and time.
|
* Requires workGroup, permits day, time and room.
|
||||||
*/
|
*/
|
||||||
NotAtSameTime,
|
NotAtSameTime,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires workGroup, permits day and time.
|
* Requires workGroup, permits day, time and room.
|
||||||
*/
|
*/
|
||||||
OnlyAfterWorkGroup
|
OnlyAfterWorkGroup,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires room, permits day, time and workGroup
|
||||||
|
*/
|
||||||
|
Room
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.kif.frontend.views
|
package de.kif.frontend.views
|
||||||
|
|
||||||
import de.kif.frontend.launch
|
import de.kif.frontend.launch
|
||||||
|
import de.kif.frontend.repository.RoomRepository
|
||||||
import de.kif.frontend.repository.WorkGroupRepository
|
import de.kif.frontend.repository.WorkGroupRepository
|
||||||
import de.westermann.kobserve.event.EventListener
|
import de.westermann.kobserve.event.EventListener
|
||||||
import de.westermann.kwebview.View
|
import de.westermann.kwebview.View
|
||||||
|
@ -10,6 +11,7 @@ import de.westermann.kwebview.createHtmlView
|
||||||
import de.westermann.kwebview.iterator
|
import de.westermann.kwebview.iterator
|
||||||
import org.w3c.dom.*
|
import org.w3c.dom.*
|
||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.clear
|
||||||
|
|
||||||
fun initWorkGroupConstraints() {
|
fun initWorkGroupConstraints() {
|
||||||
var index = 10000
|
var index = 10000
|
||||||
|
@ -149,10 +151,15 @@ fun initWorkGroupConstraints() {
|
||||||
launch {
|
launch {
|
||||||
val all = WorkGroupRepository.all()
|
val all = WorkGroupRepository.all()
|
||||||
|
|
||||||
|
val id = (select.options[select.selectedIndex] as? HTMLOptionElement)?.value
|
||||||
|
|
||||||
for (wg in all) {
|
for (wg in all) {
|
||||||
val option = createHtmlView<HTMLOptionElement>()
|
val option = createHtmlView<HTMLOptionElement>()
|
||||||
option.value = wg.id.toString()
|
option.value = wg.id.toString()
|
||||||
option.textContent = wg.name
|
option.textContent = wg.name
|
||||||
|
if (option.value == id) {
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
select.appendChild(option)
|
select.appendChild(option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,10 +184,49 @@ fun initWorkGroupConstraints() {
|
||||||
launch {
|
launch {
|
||||||
val all = WorkGroupRepository.all()
|
val all = WorkGroupRepository.all()
|
||||||
|
|
||||||
|
val id = (select.options[select.selectedIndex] as? HTMLOptionElement)?.value
|
||||||
|
|
||||||
for (wg in all) {
|
for (wg in all) {
|
||||||
val option = createHtmlView<HTMLOptionElement>()
|
val option = createHtmlView<HTMLOptionElement>()
|
||||||
option.value = wg.id.toString()
|
option.value = wg.id.toString()
|
||||||
option.textContent = wg.name
|
option.textContent = wg.name
|
||||||
|
if (option.value == id) {
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
|
select.appendChild(option)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html.appendChild(select)
|
||||||
|
}.html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addList.textView("In Raum x") {
|
||||||
|
onClick {
|
||||||
|
constraints.appendChild(View.wrap(createHtmlView<HTMLDivElement>()) {
|
||||||
|
classList += "input-group"
|
||||||
|
html.appendChild(TextView("Raum").apply {
|
||||||
|
classList += "form-btn"
|
||||||
|
onClick { this@wrap.html.remove() }
|
||||||
|
}.html)
|
||||||
|
|
||||||
|
val select = createHtmlView<HTMLSelectElement>()
|
||||||
|
select.classList.add("form-control")
|
||||||
|
select.name = "constraint-room-${index++}"
|
||||||
|
|
||||||
|
val id = (select.options[select.selectedIndex] as? HTMLOptionElement)?.value
|
||||||
|
|
||||||
|
launch {
|
||||||
|
val all = RoomRepository.all()
|
||||||
|
select.clear()
|
||||||
|
|
||||||
|
for (room in all) {
|
||||||
|
val option = createHtmlView<HTMLOptionElement>()
|
||||||
|
option.value = room.id.toString()
|
||||||
|
option.textContent = room.name
|
||||||
|
if (option.value == id) {
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
select.appendChild(option)
|
select.appendChild(option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +241,6 @@ fun initWorkGroupConstraints() {
|
||||||
val span = child.firstElementChild as HTMLElement
|
val span = child.firstElementChild as HTMLElement
|
||||||
|
|
||||||
span.addEventListener("click", org.w3c.dom.events.EventListener {
|
span.addEventListener("click", org.w3c.dom.events.EventListener {
|
||||||
println("click")
|
|
||||||
child.remove()
|
child.remove()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package de.kif.frontend.views.table
|
package de.kif.frontend.views.table
|
||||||
|
|
||||||
|
import de.kif.frontend.launch
|
||||||
|
import de.kif.frontend.repository.TrackRepository
|
||||||
import de.westermann.kwebview.components.InputView
|
import de.westermann.kwebview.components.InputView
|
||||||
import de.westermann.kwebview.iterator
|
import de.westermann.kwebview.iterator
|
||||||
import org.w3c.dom.HTMLFormElement
|
import org.w3c.dom.HTMLFormElement
|
||||||
|
@ -14,11 +16,14 @@ fun initTableLayout() {
|
||||||
|
|
||||||
val table = document.getElementsByClassName("table-layout-table")[0] as HTMLTableElement
|
val table = document.getElementsByClassName("table-layout-table")[0] as HTMLTableElement
|
||||||
|
|
||||||
|
launch {
|
||||||
|
val tracks = TrackRepository.all()
|
||||||
|
|
||||||
val list = table.getElementsByTagName("tr").iterator().asSequence().filter {
|
val list = table.getElementsByTagName("tr").iterator().asSequence().filter {
|
||||||
it.dataset["search"] != null
|
it.dataset["search"] != null
|
||||||
}.map {
|
}.map {
|
||||||
when (it.dataset["edit"]) {
|
when (it.dataset["edit"]) {
|
||||||
"workgroup" -> WorkGroupTableLine(it)
|
"workgroup" -> WorkGroupTableLine(it, tracks)
|
||||||
"room" -> RoomTableLine(it)
|
"room" -> RoomTableLine(it)
|
||||||
else -> TableLine(it)
|
else -> TableLine(it)
|
||||||
}
|
}
|
||||||
|
@ -31,4 +36,5 @@ fun initTableLayout() {
|
||||||
row.search(search.value)
|
row.search(search.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.w3c.dom.HTMLElement
|
||||||
import org.w3c.dom.HTMLSpanElement
|
import org.w3c.dom.HTMLSpanElement
|
||||||
import org.w3c.dom.get
|
import org.w3c.dom.get
|
||||||
|
|
||||||
class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
class WorkGroupTableLine(view: HTMLElement, tracks: List<Track>) : TableLine(view) {
|
||||||
|
|
||||||
private var lineId = dataset["id"]?.toLongOrNull() ?: -1
|
private var lineId = dataset["id"]?.toLongOrNull() ?: -1
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
||||||
private val spanWorkGroupLength: TextView
|
private val spanWorkGroupLength: TextView
|
||||||
private val spanWorkGroupInterested: TextView
|
private val spanWorkGroupInterested: TextView
|
||||||
private val spanWorkGroupTrack: TextView
|
private val spanWorkGroupTrack: TextView
|
||||||
private val spanWorkGroupProjector: TextView
|
|
||||||
private val spanWorkGroupResolution: TextView
|
private val spanWorkGroupResolution: TextView
|
||||||
private val spanWorkGroupLanguage: TextView
|
|
||||||
|
|
||||||
override var searchElement: SearchElement = super.searchElement
|
override var searchElement: SearchElement = super.searchElement
|
||||||
|
|
||||||
|
@ -41,12 +39,8 @@ class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
||||||
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-interested" } as HTMLSpanElement)
|
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-interested" } as HTMLSpanElement)
|
||||||
spanWorkGroupTrack =
|
spanWorkGroupTrack =
|
||||||
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-track" } as HTMLSpanElement)
|
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-track" } as HTMLSpanElement)
|
||||||
spanWorkGroupProjector =
|
|
||||||
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-projector" } as HTMLSpanElement)
|
|
||||||
spanWorkGroupResolution =
|
spanWorkGroupResolution =
|
||||||
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-resolution" } as HTMLSpanElement)
|
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-resolution" } as HTMLSpanElement)
|
||||||
spanWorkGroupLanguage =
|
|
||||||
TextView.wrap(spans.first { it.dataset["editType"] == "workgroup-language" } as HTMLSpanElement)
|
|
||||||
|
|
||||||
setupEditable(spanWorkGroupName) {
|
setupEditable(spanWorkGroupName) {
|
||||||
launch {
|
launch {
|
||||||
|
@ -77,13 +71,6 @@ class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupBoolean(spanWorkGroupProjector) {
|
|
||||||
launch {
|
|
||||||
val wg = workGroup.get()
|
|
||||||
WorkGroupRepository.update(wg.copy(projector = !wg.projector))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setupBoolean(spanWorkGroupResolution) {
|
setupBoolean(spanWorkGroupResolution) {
|
||||||
launch {
|
launch {
|
||||||
val wg = workGroup.get()
|
val wg = workGroup.get()
|
||||||
|
@ -91,19 +78,10 @@ class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupList(spanWorkGroupLanguage, Language.values().sortedBy { it.localeName }, { it.localeName }) {
|
|
||||||
if (it == null) return@setupList
|
|
||||||
launch {
|
launch {
|
||||||
val wg = workGroup.get()
|
val list = listOf<Track?>(null) + tracks
|
||||||
if (wg.language == it) return@launch
|
|
||||||
WorkGroupRepository.update(wg.copy(language = it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch {
|
setupList(spanWorkGroupTrack, list, { it.name }) {
|
||||||
val tracks = listOf<Track?>(null) + TrackRepository.all()
|
|
||||||
|
|
||||||
setupList(spanWorkGroupTrack, tracks, { it.name }) {
|
|
||||||
launch x@{
|
launch x@{
|
||||||
val wg = workGroup.get()
|
val wg = workGroup.get()
|
||||||
if (wg.track == it) return@x
|
if (wg.track == it) return@x
|
||||||
|
@ -124,9 +102,7 @@ class WorkGroupTableLine(view: HTMLElement) : TableLine(view) {
|
||||||
spanWorkGroupLength.text = wg.length.toString()
|
spanWorkGroupLength.text = wg.length.toString()
|
||||||
spanWorkGroupInterested.text = wg.interested.toString()
|
spanWorkGroupInterested.text = wg.interested.toString()
|
||||||
spanWorkGroupTrack.text = wg.track?.name ?: ""
|
spanWorkGroupTrack.text = wg.track?.name ?: ""
|
||||||
spanWorkGroupProjector.text = wg.projector.toString()
|
|
||||||
spanWorkGroupResolution.text = wg.resolution.toString()
|
spanWorkGroupResolution.text = wg.resolution.toString()
|
||||||
spanWorkGroupLanguage.text = wg.language.localeName
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,16 @@ object Configuration {
|
||||||
val timeline by c(TwitterSpec.timeline)
|
val timeline by c(TwitterSpec.timeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object ResoSpec : ConfigSpec("reso") {
|
||||||
|
val day by required<Int>()
|
||||||
|
val time by required<Int>()
|
||||||
|
}
|
||||||
|
|
||||||
|
object Reso {
|
||||||
|
val day by c(ResoSpec.day)
|
||||||
|
val time by c(ResoSpec.time)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
var config = Config {
|
var config = Config {
|
||||||
addSpec(ServerSpec)
|
addSpec(ServerSpec)
|
||||||
|
@ -119,6 +129,7 @@ object Configuration {
|
||||||
addSpec(SecuritySpec)
|
addSpec(SecuritySpec)
|
||||||
addSpec(GeneralSpec)
|
addSpec(GeneralSpec)
|
||||||
addSpec(TwitterSpec)
|
addSpec(TwitterSpec)
|
||||||
|
addSpec(ResoSpec)
|
||||||
}.from.toml.resource("portal.toml")
|
}.from.toml.resource("portal.toml")
|
||||||
|
|
||||||
for (file in Files.list(Paths.get("."))) {
|
for (file in Files.list(Paths.get("."))) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ fun Route.board() {
|
||||||
val list = ScheduleRepository.getByDay(day)
|
val list = ScheduleRepository.getByDay(day)
|
||||||
val rooms = RoomRepository.all()
|
val rooms = RoomRepository.all()
|
||||||
val schedules = list.groupBy { it.room }.mapValues { (_, it) ->
|
val schedules = list.groupBy { it.room }.mapValues { (_, it) ->
|
||||||
it.associateBy {
|
it.groupBy {
|
||||||
it.time
|
it.time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ fun DIV.renderCalendar(
|
||||||
from: Int,
|
from: Int,
|
||||||
to: Int,
|
to: Int,
|
||||||
rooms: List<Room>,
|
rooms: List<Room>,
|
||||||
schedules: Map<Room, Map<Int, Schedule>>
|
schedules: Map<Room, Map<Int, List<Schedule>>>
|
||||||
) {
|
) {
|
||||||
val gridLabelWidth = 60
|
val gridLabelWidth = 60
|
||||||
val minutesOfDay = to - from
|
val minutesOfDay = to - from
|
||||||
|
@ -144,9 +144,9 @@ fun DIV.renderCalendar(
|
||||||
|
|
||||||
title = room.name + " - " + timeString
|
title = room.name + " - " + timeString
|
||||||
|
|
||||||
val schedule = (start..end).mapNotNull { schedules[room]?.get(it) }.firstOrNull()
|
val cellSchedules = (start..end).flatMap { schedules[room]?.get(it) ?: emptyList() }
|
||||||
|
|
||||||
if (schedule != null) {
|
for(schedule in cellSchedules) {
|
||||||
calendarEntry(schedule, diff, currentTime)
|
calendarEntry(schedule, diff, currentTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ fun Route.calendar() {
|
||||||
|
|
||||||
val list = ScheduleRepository.getByDay(day)
|
val list = ScheduleRepository.getByDay(day)
|
||||||
val schedules = list.groupBy { it.room }.mapValues { (_, it) ->
|
val schedules = list.groupBy { it.room }.mapValues { (_, it) ->
|
||||||
it.associateBy {
|
it.groupBy {
|
||||||
it.time
|
it.time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import kotlin.math.min
|
||||||
|
|
||||||
data class WallData(
|
data class WallData(
|
||||||
val number: Int,
|
val number: Int,
|
||||||
val schedules: Map<Room, Map<Int, Schedule>>,
|
val schedules: Map<Room, Map<Int, List<Schedule>>>,
|
||||||
val max: Int?,
|
val max: Int?,
|
||||||
val min: Int?
|
val min: Int?
|
||||||
)
|
)
|
||||||
|
@ -26,11 +26,10 @@ suspend fun genWallData(day: Int): WallData {
|
||||||
val list = ScheduleRepository.getByDay(day)
|
val list = ScheduleRepository.getByDay(day)
|
||||||
val rooms = RoomRepository.all()
|
val rooms = RoomRepository.all()
|
||||||
|
|
||||||
if (list.isEmpty()) return WallData(day, rooms.associateWith { emptyMap<Int, Schedule>() }, null, null)
|
if (list.isEmpty()) return WallData(day, rooms.associateWith { emptyMap<Int, List<Schedule>>() }, null, null)
|
||||||
|
|
||||||
val schedules =
|
val schedules = list.groupBy { it.room }.mapValues { (_, it) ->
|
||||||
rooms.associateWith { emptyMap<Int, Schedule>() } + list.groupBy { it.room }.mapValues { (_, it) ->
|
it.groupBy {
|
||||||
it.associateBy {
|
|
||||||
it.time
|
it.time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package de.kif.backend.route
|
||||||
|
|
||||||
import de.kif.backend.authenticateOrRedirect
|
import de.kif.backend.authenticateOrRedirect
|
||||||
import de.kif.backend.prefix
|
import de.kif.backend.prefix
|
||||||
|
import de.kif.backend.repository.RoomRepository
|
||||||
import de.kif.backend.repository.TrackRepository
|
import de.kif.backend.repository.TrackRepository
|
||||||
import de.kif.backend.repository.WorkGroupRepository
|
import de.kif.backend.repository.WorkGroupRepository
|
||||||
import de.kif.backend.view.TableTemplate
|
import de.kif.backend.view.TableTemplate
|
||||||
|
@ -59,15 +60,9 @@ fun Route.workGroup() {
|
||||||
th {
|
th {
|
||||||
+"Track"
|
+"Track"
|
||||||
}
|
}
|
||||||
th {
|
|
||||||
+"Beamer"
|
|
||||||
}
|
|
||||||
th {
|
th {
|
||||||
+"Resolution"
|
+"Resolution"
|
||||||
}
|
}
|
||||||
th {
|
|
||||||
+"Sprache"
|
|
||||||
}
|
|
||||||
th(classes = "action") {
|
th(classes = "action") {
|
||||||
+"Aktion"
|
+"Aktion"
|
||||||
}
|
}
|
||||||
|
@ -111,13 +106,6 @@ fun Route.workGroup() {
|
||||||
+(u.track?.name ?: "")
|
+(u.track?.name ?: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
td {
|
|
||||||
span {
|
|
||||||
attributes["data-edit-type"] = "workgroup-projector"
|
|
||||||
|
|
||||||
+u.projector.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
td {
|
td {
|
||||||
span {
|
span {
|
||||||
attributes["data-edit-type"] = "workgroup-resolution"
|
attributes["data-edit-type"] = "workgroup-resolution"
|
||||||
|
@ -125,13 +113,6 @@ fun Route.workGroup() {
|
||||||
+u.resolution.toString()
|
+u.resolution.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
td {
|
|
||||||
span {
|
|
||||||
attributes["data-edit-type"] = "workgroup-language"
|
|
||||||
|
|
||||||
+u.language.localeName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
td(classes = "action") {
|
td(classes = "action") {
|
||||||
a("$prefix/workgroup/${u.id}") {
|
a("$prefix/workgroup/${u.id}") {
|
||||||
i("material-icons") { +"edit" }
|
i("material-icons") { +"edit" }
|
||||||
|
@ -157,6 +138,12 @@ fun Route.workGroup() {
|
||||||
WorkGroupRepository.get(it)!!
|
WorkGroupRepository.get(it)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val rooms = editWorkGroup.constraints.mapNotNull {
|
||||||
|
it.room
|
||||||
|
}.distinct().associateWith {
|
||||||
|
RoomRepository.get(it)!!
|
||||||
|
}
|
||||||
|
|
||||||
respondMain {
|
respondMain {
|
||||||
content {
|
content {
|
||||||
h1 { +"Arbeitskreis bearbeiten" }
|
h1 { +"Arbeitskreis bearbeiten" }
|
||||||
|
@ -541,6 +528,22 @@ fun Route.workGroup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ConstraintType.Room -> {
|
||||||
|
span("form-btn") {
|
||||||
|
+"Raum"
|
||||||
|
}
|
||||||
|
select(
|
||||||
|
classes = "form-control"
|
||||||
|
) {
|
||||||
|
name = "constraint-room-$index"
|
||||||
|
|
||||||
|
option {
|
||||||
|
selected = true
|
||||||
|
value = constraint.room.toString()
|
||||||
|
+(rooms[constraint.room!!]?.name ?: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -985,6 +988,9 @@ private fun parseConstraintParam(params: Map<String, String?>) = params.map { (k
|
||||||
key.startsWith("constraint-only-after-work-group") -> {
|
key.startsWith("constraint-only-after-work-group") -> {
|
||||||
value?.toLongOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyAfterWorkGroup, workGroup = it) }
|
value?.toLongOrNull()?.let { WorkGroupConstraint(ConstraintType.OnlyAfterWorkGroup, workGroup = it) }
|
||||||
}
|
}
|
||||||
|
key.startsWith("constraint-room") -> {
|
||||||
|
value?.toLongOrNull()?.let { WorkGroupConstraint(ConstraintType.Room, room = it) }
|
||||||
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}.groupBy({ it.first }) {
|
}.groupBy({ it.first }) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package de.kif.backend.route.api
|
package de.kif.backend.route.api
|
||||||
|
|
||||||
|
import de.kif.backend.Configuration
|
||||||
import de.kif.backend.authenticate
|
import de.kif.backend.authenticate
|
||||||
|
import de.kif.backend.repository.RoomRepository
|
||||||
import de.kif.backend.repository.ScheduleRepository
|
import de.kif.backend.repository.ScheduleRepository
|
||||||
import de.kif.common.checkConstraints
|
import de.kif.common.checkConstraints
|
||||||
import de.kif.common.model.Permission
|
import de.kif.common.model.Permission
|
||||||
|
@ -14,14 +16,22 @@ fun Route.constraintsApi() {
|
||||||
try {
|
try {
|
||||||
authenticate(Permission.SCHEDULE) {
|
authenticate(Permission.SCHEDULE) {
|
||||||
val schedules = ScheduleRepository.all()
|
val schedules = ScheduleRepository.all()
|
||||||
|
val rooms = RoomRepository.all()
|
||||||
|
|
||||||
val errors = checkConstraints(schedules, schedules)
|
val errors = checkConstraints(
|
||||||
|
schedules,
|
||||||
|
schedules,
|
||||||
|
rooms,
|
||||||
|
Configuration.Reso.day,
|
||||||
|
Configuration.Reso.time
|
||||||
|
)
|
||||||
|
|
||||||
call.success(errors)
|
call.success(errors)
|
||||||
} onFailure {
|
} onFailure {
|
||||||
call.error(HttpStatusCode.Unauthorized)
|
call.error(HttpStatusCode.Unauthorized)
|
||||||
}
|
}
|
||||||
} catch (_: Exception) {
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
call.error(HttpStatusCode.InternalServerError)
|
call.error(HttpStatusCode.InternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,10 +41,17 @@ fun Route.constraintsApi() {
|
||||||
authenticate(Permission.SCHEDULE) {
|
authenticate(Permission.SCHEDULE) {
|
||||||
val id = call.parameters["id"]?.toLongOrNull()
|
val id = call.parameters["id"]?.toLongOrNull()
|
||||||
val schedules = ScheduleRepository.all()
|
val schedules = ScheduleRepository.all()
|
||||||
|
val rooms = RoomRepository.all()
|
||||||
|
|
||||||
val check = schedules.filter { it.workGroup.id == id }
|
val check = schedules.filter { it.workGroup.id == id }
|
||||||
|
|
||||||
val errors = checkConstraints(check, schedules)
|
val errors = checkConstraints(
|
||||||
|
check,
|
||||||
|
schedules,
|
||||||
|
rooms,
|
||||||
|
Configuration.Reso.day,
|
||||||
|
Configuration.Reso.time
|
||||||
|
)
|
||||||
|
|
||||||
call.success(errors)
|
call.success(errors)
|
||||||
} onFailure {
|
} onFailure {
|
||||||
|
|
|
@ -16,6 +16,10 @@ reference = "1970-01-01"
|
||||||
offset = 0
|
offset = 0
|
||||||
wall_start = 0
|
wall_start = 0
|
||||||
|
|
||||||
|
[reso]
|
||||||
|
day = 0
|
||||||
|
time = 0
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
session_name = "SESSION"
|
session_name = "SESSION"
|
||||||
sign_key = "d1 20 23 8c 01 f8 f0 0d 9d 7c ff 68 21 97 75 31 38 3f fb 91 20 3a 8d 86 d4 e9 d8 50 f8 71 f1 dc"
|
sign_key = "d1 20 23 8c 01 f8 f0 0d 9d 7c ff 68 21 97 75 31 38 3f fb 91 20 3a 8d 86 d4 e9 d8 50 f8 71 f1 dc"
|
||||||
|
|
Loading…
Reference in a new issue