Add dynamic resizing of calendar
This commit is contained in:
parent
990cdaf1a4
commit
dce2567160
28 changed files with 476 additions and 254 deletions
|
@ -14,10 +14,14 @@ class WebSocketClient() {
|
|||
private val url = "ws://${window.location.host}/"
|
||||
|
||||
private lateinit var ws: WebSocket
|
||||
private var reconnect = false
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun onOpen(event: Event) {
|
||||
console.log("Connected!")
|
||||
if (reconnect) {
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMessage(messageEvent: MessageEvent) {
|
||||
|
@ -37,6 +41,7 @@ class WebSocketClient() {
|
|||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun onClose(event: Event) {
|
||||
console.log("Disconnected!")
|
||||
reconnect = true
|
||||
async(1000) {
|
||||
connect()
|
||||
}
|
||||
|
|
|
@ -6,31 +6,6 @@ import kotlin.coroutines.CoroutineContext
|
|||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.startCoroutine
|
||||
|
||||
|
||||
operator fun HTMLCollection.iterator() = object : Iterator<HTMLElement> {
|
||||
private var index = 0
|
||||
override fun hasNext(): Boolean {
|
||||
return index < this@iterator.length
|
||||
}
|
||||
|
||||
override fun next(): HTMLElement {
|
||||
return this@iterator.get(index++) as HTMLElement
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
operator fun NodeList.iterator() = object : Iterator<Node> {
|
||||
private var index = 0
|
||||
override fun hasNext(): Boolean {
|
||||
return index < this@iterator.length
|
||||
}
|
||||
|
||||
override fun next(): Node {
|
||||
return this@iterator.get(index++)!!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun launch(context: CoroutineContext = EmptyCoroutineContext, block: suspend () -> Unit) =
|
||||
block.startCoroutine(Continuation(context) { result ->
|
||||
result.onFailure { exception ->
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package de.kif.frontend.views
|
||||
|
||||
import de.kif.frontend.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.WorkGroupRepository
|
||||
import de.westermann.kobserve.event.EventListener
|
||||
|
@ -8,6 +7,7 @@ import de.westermann.kwebview.View
|
|||
import de.westermann.kwebview.async
|
||||
import de.westermann.kwebview.components.*
|
||||
import de.westermann.kwebview.createHtmlView
|
||||
import de.westermann.kwebview.iterator
|
||||
import org.w3c.dom.*
|
||||
import kotlin.browser.document
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.kif.frontend.views.board
|
||||
|
||||
import de.kif.common.formatDateTime
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.westermann.kwebview.interval
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.get
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
package de.kif.frontend.views.calendar
|
||||
|
||||
import de.kif.frontend.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.RoomRepository
|
||||
import de.kif.frontend.repository.ScheduleRepository
|
||||
import de.westermann.kwebview.View
|
||||
import de.westermann.kwebview.createHtmlView
|
||||
import de.westermann.kwebview.iterator
|
||||
import org.w3c.dom.*
|
||||
import kotlin.browser.document
|
||||
import kotlin.browser.window
|
||||
|
||||
|
||||
class Calendar(calendar: HTMLElement) : View(calendar) {
|
||||
var calendarEntries: List<CalendarEntry> = emptyList()
|
||||
var calendarCells: List<CalendarCell> = emptyList()
|
||||
|
||||
val day: Int
|
||||
val day: Int = calendar.dataset["day"]?.toIntOrNull() ?: -1
|
||||
|
||||
val htmlTag = document.body as HTMLElement
|
||||
private val htmlTag = document.body as HTMLElement
|
||||
val calendarTable = calendar.getElementsByClassName("calendar-table")[0] as HTMLElement
|
||||
val calendarTableHeader = calendar.getElementsByClassName("calendar-header")[0] as HTMLElement
|
||||
|
||||
fun scrollVerticalBy(pixel: Double, scrollBehavior: ScrollBehavior = ScrollBehavior.SMOOTH) {
|
||||
htmlTag.scrollBy(ScrollToOptions(0.0, pixel, scrollBehavior))
|
||||
|
@ -34,58 +35,22 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
|
|||
calendarTable.scrollTo(ScrollToOptions(pixel, 0.0, scrollBehavior))
|
||||
}
|
||||
|
||||
val editable = calendar.dataset["editable"]?.toBoolean() ?: false
|
||||
|
||||
val body = CalendarBody(this, calendar.getElementsByClassName("calendar-body")[0] as HTMLElement)
|
||||
|
||||
init {
|
||||
val editable = calendar.dataset["editable"]?.toBoolean() ?: false
|
||||
day = calendar.dataset["day"]?.toIntOrNull() ?: -1
|
||||
|
||||
calendarEntries = document.getElementsByClassName("calendar-entry")
|
||||
.iterator().asSequence().map { CalendarEntry(this, it) }.onEach { it.editable = editable }.toList()
|
||||
|
||||
calendarCells = document.getElementsByClassName("calendar-cell")
|
||||
.iterator().asSequence().filter { it.dataset["time"] != null }.map(::CalendarCell).toList()
|
||||
|
||||
if (editable) {
|
||||
CalendarEdit(this, calendar.querySelector(".calendar-edit") as HTMLElement)
|
||||
}
|
||||
|
||||
ScheduleRepository.onCreate {
|
||||
launch {
|
||||
val schedule = ScheduleRepository.get(it) ?: throw NoSuchElementException()
|
||||
calendarEntries += CalendarEntry.create(this, schedule).also { it.editable = editable }
|
||||
}
|
||||
}
|
||||
ScheduleRepository.onUpdate {
|
||||
launch {
|
||||
val schedule = ScheduleRepository.get(it) ?: throw NoSuchElementException()
|
||||
var found = false
|
||||
for (entry in calendarEntries) {
|
||||
if (entry.scheduleId == it) {
|
||||
entry.load(schedule)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
calendarEntries += CalendarEntry.create(this, schedule).also { it.editable = editable }
|
||||
}
|
||||
}
|
||||
}
|
||||
ScheduleRepository.onDelete {
|
||||
for (entry in calendarEntries) {
|
||||
if (entry.scheduleId == it) {
|
||||
entry.html.remove()
|
||||
calendarEntries -= entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(document.getElementById("calendar-check-constraints") as? HTMLElement)?.let { wrap(it) }?.onClick?.addListener {
|
||||
(document.getElementById("calendar-check-constraints") as? HTMLElement)?.let { wrap(it) }
|
||||
?.onClick?.addListener {
|
||||
launch {
|
||||
val errors = ScheduleRepository.checkConstraints()
|
||||
|
||||
println(errors)
|
||||
|
||||
for ((s, l) in errors.map) {
|
||||
for (entry in calendarEntries) {
|
||||
for (entry in body.calendarEntries) {
|
||||
if (entry.scheduleId == s) {
|
||||
entry.error = l.isNotEmpty()
|
||||
}
|
||||
|
@ -106,6 +71,29 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
|
|||
|
||||
it.preventDefault()
|
||||
}
|
||||
|
||||
RoomRepository.onCreate {
|
||||
val cell = createHtmlView<HTMLElement>()
|
||||
cell.dataset["room"] = it.toString()
|
||||
cell.classList.add("calendar-cell")
|
||||
calendarTableHeader.appendChild(cell)
|
||||
|
||||
launch {
|
||||
val room = RoomRepository.get(it) ?: return@launch
|
||||
val span = createHtmlView<HTMLSpanElement>()
|
||||
span.textContent = room.name
|
||||
cell.appendChild(span)
|
||||
}
|
||||
}
|
||||
|
||||
RoomRepository.onDelete {
|
||||
val str = it.toString()
|
||||
for (element in calendarTableHeader.children.iterator()) {
|
||||
if (element.dataset["room"] == str) {
|
||||
element.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
161
src/jsMain/kotlin/de/kif/frontend/views/calendar/CalendarBody.kt
Normal file
161
src/jsMain/kotlin/de/kif/frontend/views/calendar/CalendarBody.kt
Normal file
|
@ -0,0 +1,161 @@
|
|||
package de.kif.frontend.views.calendar
|
||||
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.ScheduleRepository
|
||||
import de.westermann.kwebview.ViewCollection
|
||||
import de.westermann.kwebview.interval
|
||||
import de.westermann.kwebview.iterator
|
||||
import org.w3c.dom.HTMLElement
|
||||
import kotlin.browser.document
|
||||
import kotlin.js.Date
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class CalendarBody(val calendar: Calendar, view: HTMLElement) : ViewCollection<CalendarRow>(view) {
|
||||
|
||||
val editable = calendar.editable
|
||||
val day = calendar.day
|
||||
|
||||
var calendarEntries: List<CalendarEntry> = emptyList()
|
||||
|
||||
val calendarCells: List<CalendarCell>
|
||||
get() = iterator().asSequence().flatten().toList()
|
||||
|
||||
private suspend fun updateRows(startTime: Int? = null, length: Int = 0) {
|
||||
if (calendarEntries.isEmpty() && startTime == null && !editable) {
|
||||
for (row in iterator().asSequence().toList()) {
|
||||
remove(row)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var max: Int
|
||||
var min: Int
|
||||
|
||||
if (startTime != null) {
|
||||
min = startTime
|
||||
max = startTime + length
|
||||
} else {
|
||||
min = calendarEntries.first().startTime
|
||||
max = calendarEntries.first().startTime + calendarEntries.first().length
|
||||
}
|
||||
|
||||
for (entry in calendarEntries) {
|
||||
max = max(max, entry.startTime + entry.length)
|
||||
min = min(min, entry.startTime)
|
||||
}
|
||||
|
||||
if (min > max) {
|
||||
val h1 = max
|
||||
max = min
|
||||
min = h1
|
||||
}
|
||||
|
||||
if (editable) {
|
||||
min = min(min, 0)
|
||||
max = max(max, 24 * 60)
|
||||
}
|
||||
|
||||
min = (min / 60 - 1) * 60
|
||||
max = (max / 60 + 2) * 60
|
||||
|
||||
while (isNotEmpty() && min > first().time) {
|
||||
remove(first())
|
||||
}
|
||||
|
||||
while (isNotEmpty() && max < last().time) {
|
||||
remove(last())
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
+CalendarRow.create(this, min)
|
||||
}
|
||||
|
||||
while (min < first().time) {
|
||||
prepand(CalendarRow.create(this, first().time - 15))
|
||||
}
|
||||
|
||||
while (max > last().time + 15) {
|
||||
append(CalendarRow.create(this, last().time + 15))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
calendarEntries = document.getElementsByClassName("calendar-entry")
|
||||
.iterator().asSequence().map { CalendarEntry(this, it) }.toList()
|
||||
|
||||
wrapContent {
|
||||
CalendarRow(this, it)
|
||||
}
|
||||
|
||||
ScheduleRepository.onCreate {
|
||||
launch {
|
||||
val schedule = ScheduleRepository.get(it) ?: throw NoSuchElementException()
|
||||
|
||||
updateRows(schedule.time, schedule.workGroup.length)
|
||||
|
||||
calendarEntries += CalendarEntry.create(this, schedule)
|
||||
}
|
||||
}
|
||||
ScheduleRepository.onUpdate {
|
||||
launch {
|
||||
val schedule = ScheduleRepository.get(it) ?: throw NoSuchElementException()
|
||||
|
||||
updateRows(schedule.time, schedule.workGroup.length)
|
||||
|
||||
var found = false
|
||||
for (entry in calendarEntries) {
|
||||
if (entry.scheduleId == it) {
|
||||
entry.load(schedule)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
calendarEntries += CalendarEntry.create(this, schedule)
|
||||
}
|
||||
|
||||
updateRows()
|
||||
}
|
||||
}
|
||||
ScheduleRepository.onDelete {
|
||||
for (entry in calendarEntries) {
|
||||
if (entry.scheduleId == it) {
|
||||
entry.html.remove()
|
||||
calendarEntries -= entry
|
||||
|
||||
launch {
|
||||
updateRows()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interval(1000) {
|
||||
val currentTime = Date().let {
|
||||
it.getHours() * 60 + it.getMinutes()
|
||||
}
|
||||
val rowTime = (currentTime / 15) * 15
|
||||
|
||||
for (row in this) {
|
||||
if (row.time == rowTime) {
|
||||
row.classList.clear()
|
||||
for (str in row.classList) {
|
||||
if ("now" in str) {
|
||||
row.classList -= str
|
||||
}
|
||||
}
|
||||
row.classList += "calendar-row"
|
||||
row.classList += "calendar-now"
|
||||
row.classList += "calendar-now-${currentTime - rowTime}"
|
||||
} else {
|
||||
for (str in row.classList) {
|
||||
if ("now" in str) {
|
||||
row.classList -= str
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,17 @@ package de.kif.frontend.views.calendar
|
|||
import de.kif.common.model.Room
|
||||
import de.kif.frontend.repository.RoomRepository
|
||||
import de.westermann.kwebview.ViewCollection
|
||||
import de.westermann.kwebview.createHtmlView
|
||||
import org.w3c.dom.HTMLDivElement
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.get
|
||||
import org.w3c.dom.set
|
||||
import kotlin.browser.document
|
||||
|
||||
class CalendarCell(row: CalendarRow, view: HTMLElement) : ViewCollection<CalendarEntry>(view) {
|
||||
val day = row.day
|
||||
val time = row.time
|
||||
|
||||
class CalendarCell(view: HTMLElement) : ViewCollection<CalendarEntry>(view) {
|
||||
val day = dataset["day"]?.toIntOrNull() ?: 0
|
||||
val time = dataset["time"]?.toIntOrNull() ?: 0
|
||||
val roomId = dataset["room"]?.toLongOrNull() ?: 0
|
||||
|
||||
private lateinit var room: Room
|
||||
|
@ -22,7 +27,13 @@ class CalendarCell(view: HTMLElement) : ViewCollection<CalendarEntry>(view) {
|
|||
return room
|
||||
}
|
||||
|
||||
init {
|
||||
(view.getElementsByClassName("calendar-link")[0] as? HTMLElement)?.remove()
|
||||
companion object {
|
||||
fun create(row: CalendarRow, roomId: Long): CalendarCell {
|
||||
val view = createHtmlView<HTMLDivElement>()
|
||||
view.classList.add("calendar-cell")
|
||||
view.dataset["room"] = roomId.toString()
|
||||
|
||||
return CalendarCell(row, view)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package de.kif.frontend.views.calendar
|
||||
|
||||
import de.kif.common.CALENDAR_GRID_WIDTH
|
||||
import de.kif.common.model.Room
|
||||
import de.kif.common.model.Schedule
|
||||
import de.kif.common.model.WorkGroup
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.RepositoryDelegate
|
||||
import de.kif.frontend.repository.ScheduleRepository
|
||||
|
@ -17,7 +16,7 @@ import kotlin.dom.appendText
|
|||
import kotlin.dom.isText
|
||||
import kotlin.js.Date
|
||||
|
||||
class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(view) {
|
||||
class CalendarEntry(private val calendar: CalendarBody, view: HTMLElement) : View(view) {
|
||||
|
||||
private lateinit var mouseDelta: Point
|
||||
private var newCell: CalendarCell? = null
|
||||
|
@ -31,11 +30,15 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
|
||||
private lateinit var workGroup: WorkGroup
|
||||
|
||||
var startTime = dataset["time"]?.toIntOrNull() ?: 0
|
||||
var length = dataset["length"]?.toIntOrNull() ?: 0
|
||||
|
||||
var pending by classList.property("pending")
|
||||
var error by classList.property("error")
|
||||
private var nextScroll = 0.0
|
||||
|
||||
var editable: Boolean = false
|
||||
val editable: Boolean
|
||||
get() = calendar.editable
|
||||
|
||||
var moveLookRoom: Long? = null
|
||||
var moveLookTime: Int? = null
|
||||
|
@ -48,7 +51,7 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
}
|
||||
|
||||
if (cell != null) {
|
||||
if (moveLookRoom != null && cell.roomId != moveLookRoom) {
|
||||
if (moveLookRoom != null && cell.roomId != moveLookRoom) {
|
||||
return
|
||||
}
|
||||
if (moveLookTime != null && cell.time != moveLookTime) {
|
||||
|
@ -70,29 +73,29 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
return@async
|
||||
}
|
||||
|
||||
val width = calendar.calendarTable.clientWidth
|
||||
val width = calendar.calendar.calendarTable.clientWidth
|
||||
val height = window.innerHeight
|
||||
val rect = html.getBoundingClientRect()
|
||||
|
||||
if (rect.left < 0.0) {
|
||||
nextScroll = now + 500.0
|
||||
calendar.scrollHorizontalBy(rect.left - 80.0)
|
||||
calendar.calendar.scrollHorizontalBy(rect.left - 80.0)
|
||||
} else if (rect.right > width) {
|
||||
nextScroll = now + 0.500
|
||||
calendar.scrollHorizontalBy(rect.right - width + 50.0)
|
||||
calendar.calendar.scrollHorizontalBy(rect.right - width + 50.0)
|
||||
}
|
||||
|
||||
if (rect.top < 20.0) {
|
||||
nextScroll = now + 500.0
|
||||
calendar.scrollVerticalBy(rect.top - 50.0)
|
||||
calendar.calendar.scrollVerticalBy(rect.top - 50.0)
|
||||
} else if (rect.bottom > height - 20.0) {
|
||||
nextScroll = now + 500.0
|
||||
calendar.scrollVerticalBy(rect.bottom - height + 50.0)
|
||||
calendar.calendar.scrollVerticalBy(rect.bottom - height + 50.0)
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
calendarTools.setName(cell.getRoom(), cell.time)
|
||||
calendarTools?.setName(cell.getRoom(), cell.time)
|
||||
}
|
||||
|
||||
newCell = cell
|
||||
|
@ -153,7 +156,7 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
)
|
||||
}
|
||||
|
||||
private val calendarTools = CalendarTools(this)
|
||||
private val calendarTools = if (editable) CalendarTools(this) else null
|
||||
|
||||
init {
|
||||
onMouseDown { event ->
|
||||
|
@ -181,11 +184,13 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
event.stopPropagation()
|
||||
}
|
||||
|
||||
html.appendChild(calendarTools.html)
|
||||
if (calendarTools != null) {
|
||||
html.appendChild(calendarTools.html)
|
||||
|
||||
launch {
|
||||
val s = schedule.get()
|
||||
calendarTools.update(s)
|
||||
launch {
|
||||
val s = schedule.get()
|
||||
calendarTools.update(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +210,10 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
}
|
||||
|
||||
load(schedule.workGroup)
|
||||
calendarTools.update(schedule)
|
||||
calendarTools?.update(schedule)
|
||||
|
||||
startTime = schedule.time
|
||||
length = schedule.workGroup.length
|
||||
|
||||
val time = schedule.time / CALENDAR_GRID_WIDTH * CALENDAR_GRID_WIDTH
|
||||
val cell = calendar.calendarCells.find {
|
||||
|
@ -247,7 +255,7 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun create(calendar: Calendar, schedule: Schedule): CalendarEntry {
|
||||
fun create(calendar: CalendarBody, schedule: Schedule): CalendarEntry {
|
||||
val entry = CalendarEntry(calendar, createHtmlView())
|
||||
|
||||
entry.load(schedule)
|
||||
|
@ -255,7 +263,7 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
|
|||
return entry
|
||||
}
|
||||
|
||||
fun create(calendar: Calendar, workGroup: WorkGroup): CalendarEntry {
|
||||
fun create(calendar: CalendarBody, workGroup: WorkGroup): CalendarEntry {
|
||||
val entry = CalendarEntry(calendar, createHtmlView())
|
||||
|
||||
entry.load(workGroup)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package de.kif.frontend.views.calendar
|
||||
|
||||
import de.kif.frontend.repository.RoomRepository
|
||||
import de.westermann.kwebview.ViewCollection
|
||||
import de.westermann.kwebview.createHtmlView
|
||||
import org.w3c.dom.HTMLDivElement
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.HTMLSpanElement
|
||||
import org.w3c.dom.set
|
||||
|
||||
class CalendarRow(calendar: CalendarBody, view: HTMLElement) : ViewCollection<CalendarCell>(view) {
|
||||
val day = calendar.day
|
||||
|
||||
val time = dataset["time"]?.toIntOrNull() ?: 0
|
||||
|
||||
init {
|
||||
wrapContent {
|
||||
CalendarCell(this, it)
|
||||
}
|
||||
|
||||
RoomRepository.onCreate {
|
||||
+CalendarCell.create(this, it)
|
||||
}
|
||||
RoomRepository.onDelete { id ->
|
||||
find { it.roomId == id }?.let(this@CalendarRow::remove)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun create(calendar: CalendarBody, time: Int): CalendarRow {
|
||||
val view = createHtmlView<HTMLDivElement>()
|
||||
view.classList.add("calendar-row")
|
||||
view.dataset["time"] = time.toString()
|
||||
|
||||
val row = CalendarRow(calendar, view)
|
||||
|
||||
val rowHeader = createHtmlView<HTMLElement>()
|
||||
rowHeader.classList.add("calendar-cell")
|
||||
if (time % 60 == 0) {
|
||||
val span = createHtmlView<HTMLSpanElement>()
|
||||
|
||||
val t = (time % (60 * 24)).let {
|
||||
if (it < 0) it + 60 * 24 else it
|
||||
}
|
||||
val hours = (t / 60).toString().padStart(2, '0')
|
||||
span.textContent = "$hours:00"
|
||||
|
||||
rowHeader.appendChild(span)
|
||||
}
|
||||
row.html.appendChild(rowHeader)
|
||||
|
||||
row.html
|
||||
|
||||
val rooms = RoomRepository.all()
|
||||
|
||||
for (room in rooms) {
|
||||
if (room.id != null) {
|
||||
row += CalendarCell.create(row, room.id)
|
||||
}
|
||||
}
|
||||
|
||||
return row
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ class CalendarWorkGroup(
|
|||
}
|
||||
|
||||
onMouseDown {
|
||||
CalendarEntry.create(calendar, workGroup)
|
||||
CalendarEntry.create(calendar.body, workGroup)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package de.kif.frontend.views.overview
|
||||
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.PostRepository
|
||||
import de.westermann.kobserve.event.subscribe
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.kif.frontend.views.table
|
||||
|
||||
import de.kif.common.SearchElement
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.RepositoryDelegate
|
||||
import de.kif.frontend.repository.RoomRepository
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package de.kif.frontend.views.table
|
||||
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.westermann.kwebview.components.InputView
|
||||
import org.w3c.dom.HTMLFormElement
|
||||
import org.w3c.dom.HTMLInputElement
|
||||
|
|
|
@ -3,7 +3,7 @@ package de.kif.frontend.views.table
|
|||
import de.kif.common.SearchElement
|
||||
import de.kif.common.model.Language
|
||||
import de.kif.common.model.Track
|
||||
import de.kif.frontend.iterator
|
||||
import de.westermann.kwebview.iterator
|
||||
import de.kif.frontend.launch
|
||||
import de.kif.frontend.repository.RepositoryDelegate
|
||||
import de.kif.frontend.repository.TrackRepository
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
package de.westermann.kwebview
|
||||
|
||||
import de.westermann.kobserve.event.EventListener
|
||||
import de.westermann.kobserve.Property
|
||||
import de.westermann.kobserve.ReadOnlyProperty
|
||||
import de.westermann.kobserve.event.EventListener
|
||||
import de.westermann.kobserve.property.property
|
||||
import org.w3c.dom.DOMTokenList
|
||||
import kotlin.collections.Iterable
|
||||
import kotlin.collections.Iterator
|
||||
import kotlin.collections.MutableMap
|
||||
import kotlin.collections.contains
|
||||
import kotlin.collections.minusAssign
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
|
||||
/**
|
||||
* Represents the css classes of an html element.
|
||||
|
@ -12,7 +19,7 @@ import org.w3c.dom.DOMTokenList
|
|||
* @author lars
|
||||
*/
|
||||
class ClassList(
|
||||
private val list: DOMTokenList
|
||||
private val list: DOMTokenList
|
||||
) : Iterable<String> {
|
||||
|
||||
private val bound: MutableMap<String, Bound> = mutableMapOf()
|
||||
|
@ -74,11 +81,11 @@ class ClassList(
|
|||
* Set css class present.
|
||||
*/
|
||||
operator fun set(clazz: String, present: Boolean) =
|
||||
if (present) {
|
||||
add(clazz)
|
||||
} else {
|
||||
remove(clazz)
|
||||
}
|
||||
if (present) {
|
||||
add(clazz)
|
||||
} else {
|
||||
remove(clazz)
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle css class.
|
||||
|
@ -92,9 +99,9 @@ class ClassList(
|
|||
|
||||
set(clazz, property.value)
|
||||
bound[clazz] = Bound(property,
|
||||
property.onChange.reference {
|
||||
list.toggle(clazz, property.value)
|
||||
}
|
||||
property.onChange.reference {
|
||||
list.toggle(clazz, property.value)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -130,8 +137,14 @@ class ClassList(
|
|||
|
||||
override fun toString(): String = list.value
|
||||
|
||||
fun clear() {
|
||||
for (element in this) {
|
||||
remove(element)
|
||||
}
|
||||
}
|
||||
|
||||
private data class Bound(
|
||||
val property: ReadOnlyProperty<Boolean>,
|
||||
val reference: EventListener<Unit>?
|
||||
val property: ReadOnlyProperty<Boolean>,
|
||||
val reference: EventListener<Unit>?
|
||||
)
|
||||
}
|
|
@ -8,7 +8,15 @@ import kotlin.dom.clear
|
|||
*/
|
||||
abstract class ViewCollection<V : View>(view: HTMLElement = createHtmlView()) : View(view), Collection<V> {
|
||||
|
||||
private val children: MutableList<V> = mutableListOf()
|
||||
protected val children: MutableList<V> = mutableListOf()
|
||||
|
||||
protected inline fun <reified T : HTMLElement> wrapContent(transform: (T) -> V) {
|
||||
for (element in html.children.iterator()) {
|
||||
children += transform(element as T)
|
||||
}
|
||||
}
|
||||
|
||||
protected inline fun wrapContent(transform: (HTMLElement) -> V) = wrapContent<HTMLElement>(transform)
|
||||
|
||||
fun append(view: V) {
|
||||
children += view
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package de.westermann.kwebview
|
||||
|
||||
import de.westermann.kobserve.event.EventHandler
|
||||
import org.w3c.dom.DOMRect
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.*
|
||||
import org.w3c.dom.events.Event
|
||||
import org.w3c.dom.events.EventListener
|
||||
import org.w3c.dom.events.MouseEvent
|
||||
|
@ -11,6 +10,30 @@ import org.w3c.xhr.XMLHttpRequest
|
|||
import kotlin.browser.document
|
||||
import kotlin.browser.window
|
||||
|
||||
operator fun HTMLCollection.iterator() = object : Iterator<HTMLElement> {
|
||||
private var index = 0
|
||||
override fun hasNext(): Boolean {
|
||||
return index < this@iterator.length
|
||||
}
|
||||
|
||||
override fun next(): HTMLElement {
|
||||
return this@iterator.get(index++) as HTMLElement
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
operator fun NodeList.iterator() = object : Iterator<Node> {
|
||||
private var index = 0
|
||||
override fun hasNext(): Boolean {
|
||||
return index < this@iterator.length
|
||||
}
|
||||
|
||||
override fun next(): Node {
|
||||
return this@iterator.get(index++)!!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified V : HTMLElement> createHtmlView(tag: String? = null): V {
|
||||
var tagName: String
|
||||
if (tag != null) {
|
||||
|
|
|
@ -384,7 +384,7 @@
|
|||
border-left: none;
|
||||
}
|
||||
|
||||
&:nth-child(4n + 2) .calendar-cell::before {
|
||||
&:nth-child(4n + 1) .calendar-cell::before {
|
||||
border-top: solid 1px var(--table-border-color);
|
||||
}
|
||||
|
||||
|
@ -424,6 +424,10 @@
|
|||
&.time-to-room {
|
||||
flex-direction: row;
|
||||
|
||||
.calendar-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.calendar-header, .calendar-row {
|
||||
flex-direction: column;
|
||||
line-height: 3rem;
|
||||
|
@ -468,7 +472,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
&:nth-child(2n + 2) .calendar-cell::before {
|
||||
&:nth-child(4n + 1) .calendar-cell::before {
|
||||
content: '';
|
||||
height: 100%;
|
||||
left: 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue