Update brett
This commit is contained in:
parent
d52ada1726
commit
0026643a0a
11 changed files with 197 additions and 71 deletions
|
@ -6,6 +6,7 @@ debug = false
|
||||||
|
|
||||||
[schedule]
|
[schedule]
|
||||||
reference = "2019-06-10"
|
reference = "2019-06-10"
|
||||||
|
offset = 7200000
|
||||||
|
|
||||||
[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"
|
||||||
|
|
|
@ -4,37 +4,52 @@ import com.soywiz.klock.DateFormat
|
||||||
import com.soywiz.klock.KlockLocale
|
import com.soywiz.klock.KlockLocale
|
||||||
import com.soywiz.klock.format
|
import com.soywiz.klock.format
|
||||||
import com.soywiz.klock.locale.german
|
import com.soywiz.klock.locale.german
|
||||||
import com.soywiz.klock.min
|
|
||||||
|
|
||||||
fun formatDateTime(unix: Long) =
|
fun formatDateTime(unix: Long) =
|
||||||
DateFormat("EEEE, d. MMMM y HH:mm")
|
DateFormat("EEEE, d. MMMM y HH:mm")
|
||||||
.withLocale(KlockLocale.german)
|
.withLocale(KlockLocale.german)
|
||||||
.format(unix)
|
.format(unix)
|
||||||
|
|
||||||
fun formatTimeDiff(diff: Long): String {
|
fun formatTimeDiff(time: Long, now: Long): String {
|
||||||
var time = diff / 1000
|
var dt = (time - now) / 1000
|
||||||
|
|
||||||
val seconds = time % 60
|
val seconds = dt % 60
|
||||||
time /= 60
|
dt /= 60
|
||||||
val minutes = time % 60
|
val minutes = dt % 60
|
||||||
time /= 60
|
dt /= 60
|
||||||
val hours = time % 24
|
val hours = dt % 24
|
||||||
time /= 24
|
dt /= 24
|
||||||
val days = time
|
val days = dt
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
|
days > 1L -> {
|
||||||
|
"in $days Tagen"
|
||||||
|
}
|
||||||
days > 0L -> {
|
days > 0L -> {
|
||||||
if (days == 1L) "1 Tag" else "$days Tagen"
|
"morgen"
|
||||||
|
}
|
||||||
|
hours > 1L -> {
|
||||||
|
val nowHour = DateFormat("HH")
|
||||||
|
.withLocale(KlockLocale.german)
|
||||||
|
.format(now).toInt() ?: 0
|
||||||
|
|
||||||
|
val ht = DateFormat("HH:mm")
|
||||||
|
.withLocale(KlockLocale.german)
|
||||||
|
.format(time)
|
||||||
|
|
||||||
|
if ((ht.substringBefore(":").toIntOrNull() ?: 0) < nowHour ) {
|
||||||
|
"morgen"
|
||||||
|
} else "um $ht"
|
||||||
}
|
}
|
||||||
hours > 0L -> {
|
hours > 0L -> {
|
||||||
hours.toString().padStart(2, '0')+":"+ (minutes + if (seconds > 0) 1 else 0).toString().padStart(2,'0')
|
"in " +hours.toString().padStart(2, '0') + ":" + (minutes + if (seconds > 0) 1 else 0).toString().padStart(2, '0')
|
||||||
}
|
}
|
||||||
minutes > 0L -> {
|
minutes > 0L -> {
|
||||||
"00:"+ (minutes+ if (seconds > 0) 1 else 0).toString().padStart(2,'0')
|
"in 00:" + (minutes + if (seconds > 0) 1 else 0).toString().padStart(2, '0')
|
||||||
}
|
}
|
||||||
seconds > 0L -> {
|
seconds > 0L -> {
|
||||||
"> 1 Minute"
|
"in > 1 Minute"
|
||||||
}
|
}
|
||||||
else -> "vor $minutes Minuten"
|
else -> "---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ object ScheduleRepository : Repository<Schedule> {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUpcoming(count: Int = 8): List<Schedule> {
|
suspend fun getUpcoming(count: Int = 8): List<Schedule> {
|
||||||
val json = repositoryGet("$prefix/api/schedule/upcoming?count=$count") ?: return emptyList()
|
val json = repositoryGet("$prefix/api/schedules/upcoming?count=$count") ?: return emptyList()
|
||||||
return parser.parse(json, Schedule.serializer().list)
|
return parser.parse(json, Schedule.serializer().list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ package de.kif.frontend.views.board
|
||||||
import com.soywiz.klock.DateFormat
|
import com.soywiz.klock.DateFormat
|
||||||
import com.soywiz.klock.DateTimeTz
|
import com.soywiz.klock.DateTimeTz
|
||||||
import com.soywiz.klock.KlockLocale
|
import com.soywiz.klock.KlockLocale
|
||||||
import com.soywiz.klock.format
|
|
||||||
import com.soywiz.klock.locale.german
|
import com.soywiz.klock.locale.german
|
||||||
|
import de.kif.frontend.launch
|
||||||
|
import de.kif.frontend.repository.ScheduleRepository
|
||||||
import de.kif.frontend.views.overview.getByClassOrCreate
|
import de.kif.frontend.views.overview.getByClassOrCreate
|
||||||
import de.westermann.kwebview.interval
|
import de.westermann.kwebview.interval
|
||||||
import de.westermann.kwebview.iterator
|
import de.westermann.kwebview.iterator
|
||||||
|
@ -12,6 +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
|
||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
|
import kotlin.dom.clear
|
||||||
import kotlin.js.Date
|
import kotlin.js.Date
|
||||||
|
|
||||||
fun initBoard() {
|
fun initBoard() {
|
||||||
|
@ -20,16 +22,37 @@ fun initBoard() {
|
||||||
val timeView = dateContainer.getByClassOrCreate<HTMLSpanElement>("board-header-date-time")
|
val timeView = dateContainer.getByClassOrCreate<HTMLSpanElement>("board-header-date-time")
|
||||||
val dateView = dateContainer.getByClassOrCreate<HTMLSpanElement>("board-header-date-date")
|
val dateView = dateContainer.getByClassOrCreate<HTMLSpanElement>("board-header-date-date")
|
||||||
|
|
||||||
val initTime = Date.now().toLong()
|
val initTime = Date.now().toLong()
|
||||||
val referenceInitTime = dateContainer.dataset["now"]?.toLongOrNull() ?: initTime
|
val referenceInitTime = dateContainer.dataset["now"]?.toLongOrNull() ?: initTime
|
||||||
val diff = initTime - referenceInitTime
|
val diff = initTime - referenceInitTime
|
||||||
|
|
||||||
|
|
||||||
val boardRunning = document.getElementsByClassName("board-running")[0] as HTMLElement
|
val boardRunning = document.getElementsByClassName("board-running")[0] as HTMLElement
|
||||||
val scheduleList = mutableListOf<BoardSchedule>()
|
val scheduleList = mutableListOf<BoardSchedule>()
|
||||||
|
val runningReferenceTime = boardRunning.dataset["reference"]?.toLongOrNull() ?: 0L
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
launch {
|
||||||
|
scheduleList.clear()
|
||||||
|
val list = ScheduleRepository.getUpcoming()
|
||||||
|
boardRunning.clear()
|
||||||
|
|
||||||
|
val now = Date.now().toLong() + diff
|
||||||
|
|
||||||
|
for (s in list) {
|
||||||
|
val v = BoardSchedule.create(s, runningReferenceTime, now)
|
||||||
|
scheduleList += v
|
||||||
|
boardRunning.appendChild(v.html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (bs in boardRunning.getElementsByClassName("board-schedule").iterator()) {
|
for (bs in boardRunning.getElementsByClassName("board-schedule").iterator()) {
|
||||||
scheduleList += BoardSchedule(bs)
|
scheduleList += BoardSchedule(bs).also {
|
||||||
|
it.onRemove {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interval(1000) {
|
interval(1000) {
|
||||||
|
@ -48,4 +71,14 @@ fun initBoard() {
|
||||||
|
|
||||||
scheduleList.forEach { it.updateTime(now) }
|
scheduleList.forEach { it.updateTime(now) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScheduleRepository.onCreate {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
ScheduleRepository.onUpdate {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
ScheduleRepository.onDelete {
|
||||||
|
update()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,67 @@
|
||||||
package de.kif.frontend.views.board
|
package de.kif.frontend.views.board
|
||||||
|
|
||||||
import de.kif.common.formatDateTime
|
|
||||||
import de.kif.common.formatTimeDiff
|
import de.kif.common.formatTimeDiff
|
||||||
import de.kif.common.model.Schedule
|
import de.kif.common.model.Schedule
|
||||||
import de.kif.frontend.views.overview.getByClassOrCreate
|
import de.kif.frontend.views.overview.getByClassOrCreate
|
||||||
|
import de.westermann.kobserve.event.EventHandler
|
||||||
import de.westermann.kwebview.View
|
import de.westermann.kwebview.View
|
||||||
|
import de.westermann.kwebview.createHtmlView
|
||||||
import org.w3c.dom.HTMLDivElement
|
import org.w3c.dom.HTMLDivElement
|
||||||
import org.w3c.dom.HTMLElement
|
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
|
||||||
import kotlin.js.Date
|
|
||||||
|
|
||||||
class BoardSchedule(
|
class BoardSchedule(
|
||||||
view: HTMLElement
|
view: HTMLElement,
|
||||||
|
startTime: Long = 0L,
|
||||||
|
endTime: Long = 0L
|
||||||
) : View(view) {
|
) : View(view) {
|
||||||
private val colorView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-color")
|
val colorViewContainer = view.getByClassOrCreate<HTMLDivElement>("board-schedule-color")
|
||||||
private val timeView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-time")
|
val colorView = colorViewContainer.getByClassOrCreate<HTMLSpanElement>("bsc")
|
||||||
private val nameView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-name")
|
val timeView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-time")
|
||||||
private val roomView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-room")
|
val nameView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-name")
|
||||||
|
val roomView = view.getByClassOrCreate<HTMLDivElement>("board-schedule-room")
|
||||||
|
|
||||||
private val schedule: Long = view.dataset["id"]?.toLongOrNull() ?: 0L
|
|
||||||
private val startTime: Long = timeView.dataset["startTime"]?.toLongOrNull() ?: 0L
|
val clockViewContainer = view.getByClassOrCreate<HTMLDivElement>("board-schedule-clock")
|
||||||
private val endTime: Long = timeView.dataset["endTime"]?.toLongOrNull() ?: 0L
|
val clockView = clockViewContainer.getByClassOrCreate<HTMLElement>("material-icons", "i").also {
|
||||||
|
it.textContent = "alarm"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val startTime: Long = timeView.dataset["startTime"]?.toLongOrNull() ?: startTime
|
||||||
|
private val endTime: Long = timeView.dataset["endTime"]?.toLongOrNull() ?: endTime
|
||||||
|
|
||||||
|
val onRemove = EventHandler<Unit>()
|
||||||
|
|
||||||
fun updateTime(now: Long) {
|
fun updateTime(now: Long) {
|
||||||
timeView.textContent = if (startTime >= now) {
|
timeView.textContent = when {
|
||||||
"Start in ${formatTimeDiff(startTime - now)}"
|
startTime >= now -> "Start ${formatTimeDiff(startTime, now)}"
|
||||||
} else {
|
endTime >= now -> "Ende ${formatTimeDiff(endTime, now)}"
|
||||||
"Ende in ${formatTimeDiff(endTime - now)}"
|
else -> {
|
||||||
|
onRemove.emit(Unit)
|
||||||
|
"---"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
classList["board-schedule-running"] = now in startTime..endTime
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
companion object {
|
||||||
|
fun create(schedule: Schedule, referenceTime: Long, now: Long): BoardSchedule {
|
||||||
|
val startTime = ((schedule.getAbsoluteStartTime() * 60 * 1000) + referenceTime)
|
||||||
|
val endTime = ((schedule.getAbsoluteEndTime() * 60 * 1000) + referenceTime)
|
||||||
|
|
||||||
|
val entry = BoardSchedule(createHtmlView(), startTime, endTime)
|
||||||
|
|
||||||
|
if (schedule.workGroup.track?.color != null) {
|
||||||
|
entry.colorView.style.backgroundColor = schedule.workGroup.track.color.toString()
|
||||||
|
}
|
||||||
|
entry.nameView.textContent = schedule.workGroup.name
|
||||||
|
entry.roomView.textContent = schedule.room.name
|
||||||
|
|
||||||
|
entry.updateTime(now)
|
||||||
|
|
||||||
|
return entry
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,17 @@
|
||||||
&:first-child {
|
&:first-child {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
float: left;
|
float: left;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -1rem;
|
||||||
|
bottom: 0;
|
||||||
|
left: 100%;
|
||||||
|
margin-left: 1rem;
|
||||||
|
border-right: solid 1px var(--table-border-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -38,6 +49,16 @@
|
||||||
& > div {
|
& > div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
top: 100%;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
border-bottom: solid 1px var(--table-border-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.board-content {
|
.board-content {
|
||||||
|
@ -71,10 +92,23 @@
|
||||||
border-bottom: solid 1px var(--table-border-color);
|
border-bottom: solid 1px var(--table-border-color);
|
||||||
width: calc(50% - 1rem);
|
width: calc(50% - 1rem);
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
&:nth-last-child(1), &:nth-last-child(2) {
|
&:nth-last-child(1), &:nth-last-child(2) {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.board-schedule-clock {
|
||||||
|
position: absolute;
|
||||||
|
left: 1rem;
|
||||||
|
top: 0;
|
||||||
|
display: none;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.board-schedule-running .board-schedule-clock {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.board-schedule-color {
|
.board-schedule-color {
|
||||||
|
|
|
@ -504,7 +504,7 @@
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3rem;
|
top: 0.1rem;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
border-right: solid 1px var(--primary-color);
|
border-right: solid 1px var(--primary-color);
|
||||||
|
@ -514,7 +514,7 @@
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 3rem;
|
top: 0.1rem;
|
||||||
transform: scale(0.5, 1) rotate(45deg);
|
transform: scale(0.5, 1) rotate(45deg);
|
||||||
transform-origin: right;
|
transform-origin: right;
|
||||||
border-bottom: solid 0.4rem var(--primary-color);
|
border-bottom: solid 0.4rem var(--primary-color);
|
||||||
|
|
|
@ -60,6 +60,7 @@ object Configuration {
|
||||||
|
|
||||||
private object ScheduleSpec : ConfigSpec("schedule") {
|
private object ScheduleSpec : ConfigSpec("schedule") {
|
||||||
val reference by required<String>()
|
val reference by required<String>()
|
||||||
|
val offset by required<Long>()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Schedule {
|
object Schedule {
|
||||||
|
@ -69,6 +70,8 @@ object Configuration {
|
||||||
sdf.timeZone = TimeZone.getTimeZone(ZoneId.of("UTC"))
|
sdf.timeZone = TimeZone.getTimeZone(ZoneId.of("UTC"))
|
||||||
sdf.parse(reference)
|
sdf.parse(reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val offset by c(ScheduleSpec.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
private object SecuritySpec : ConfigSpec("security") {
|
private object SecuritySpec : ConfigSpec("security") {
|
||||||
|
|
|
@ -10,10 +10,7 @@ import io.ktor.routing.Route
|
||||||
import io.ktor.routing.get
|
import io.ktor.routing.get
|
||||||
import kotlinx.css.CSSBuilder
|
import kotlinx.css.CSSBuilder
|
||||||
import kotlinx.css.Color
|
import kotlinx.css.Color
|
||||||
import kotlinx.html.div
|
import kotlinx.html.*
|
||||||
import kotlinx.html.img
|
|
||||||
import kotlinx.html.span
|
|
||||||
import kotlinx.html.unsafe
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -25,8 +22,10 @@ data class BoardSchedule(
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun getUpcoming(limit: Int = 8): List<Schedule> {
|
suspend fun getUpcoming(limit: Int = 8): List<Schedule> {
|
||||||
val now = (Date().time / (1000 * 60)).toInt() - (Configuration.Schedule.referenceDate.time / (1000 * 60))
|
val now =
|
||||||
return ScheduleRepository.all().asSequence()
|
((Date().time + Configuration.Schedule.offset) / (1000 * 60)).toInt() -
|
||||||
|
(Configuration.Schedule.referenceDate.time / (1000 * 60))
|
||||||
|
return ScheduleRepository.all()
|
||||||
.map {
|
.map {
|
||||||
BoardSchedule(
|
BoardSchedule(
|
||||||
it,
|
it,
|
||||||
|
@ -35,10 +34,11 @@ suspend fun getUpcoming(limit: Int = 8): List<Schedule> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.filter { it.endTime > now }
|
.filter { it.endTime > now }
|
||||||
.sortedBy { it.startTime }
|
.partition { it.startTime < now }.let { (running, upcoming) ->
|
||||||
|
running.sortedBy { it.endTime } + upcoming.sortedBy { it.startTime }
|
||||||
|
}
|
||||||
.take(limit)
|
.take(limit)
|
||||||
.map { it.schedule }
|
.map { it.schedule }
|
||||||
.toList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Route.board() {
|
fun Route.board() {
|
||||||
|
@ -47,6 +47,7 @@ fun Route.board() {
|
||||||
|
|
||||||
val now = Date()
|
val now = Date()
|
||||||
val referenceTime = Configuration.Schedule.referenceDate.time
|
val referenceTime = Configuration.Schedule.referenceDate.time
|
||||||
|
val timeOffset = Configuration.Schedule.offset
|
||||||
|
|
||||||
val refDate = Configuration.Schedule.referenceDate
|
val refDate = Configuration.Schedule.referenceDate
|
||||||
|
|
||||||
|
@ -83,17 +84,28 @@ fun Route.board() {
|
||||||
min = (min / 60 - 1) * 60
|
min = (min / 60 - 1) * 60
|
||||||
max = (max / 60 + 2) * 60
|
max = (max / 60 + 2) * 60
|
||||||
|
|
||||||
|
val nowLocale = now.time + timeOffset
|
||||||
respondMain(true, true) { theme ->
|
respondMain(true, true) { theme ->
|
||||||
content {
|
content {
|
||||||
div("board") {
|
div("board") {
|
||||||
div("board-header") {
|
div("board-header") {
|
||||||
div("board-running") {
|
div("board-running") {
|
||||||
|
attributes["data-reference"] = referenceTime.toString()
|
||||||
|
|
||||||
for (schedule in scheduleList) {
|
for (schedule in scheduleList) {
|
||||||
div("board-schedule") {
|
val startTime = ((schedule.getAbsoluteStartTime() * 60 * 1000) + referenceTime)
|
||||||
|
val endTime = ((schedule.getAbsoluteEndTime() * 60 * 1000) + referenceTime)
|
||||||
|
|
||||||
|
var classes = "board-schedule"
|
||||||
|
if (nowLocale in startTime..endTime) {
|
||||||
|
classes += " board-schedule-running"
|
||||||
|
}
|
||||||
|
|
||||||
|
div(classes) {
|
||||||
attributes["data-id"] = schedule.id.toString()
|
attributes["data-id"] = schedule.id.toString()
|
||||||
|
|
||||||
div("board-schedule-color") {
|
div("board-schedule-color") {
|
||||||
span {
|
span("bsc") {
|
||||||
attributes["style"] = CSSBuilder().apply {
|
attributes["style"] = CSSBuilder().apply {
|
||||||
val c = schedule.workGroup.track?.color
|
val c = schedule.workGroup.track?.color
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
|
@ -104,16 +116,14 @@ fun Route.board() {
|
||||||
}
|
}
|
||||||
|
|
||||||
div("board-schedule-time") {
|
div("board-schedule-time") {
|
||||||
val startTime = ((schedule.getAbsoluteStartTime() * 60 * 1000) + referenceTime)
|
|
||||||
val endTime = ((schedule.getAbsoluteEndTime() * 60 * 1000) + referenceTime)
|
|
||||||
|
|
||||||
attributes["data-start-time"] = startTime.toString()
|
attributes["data-start-time"] = startTime.toString()
|
||||||
attributes["data-end-time"] = endTime.toString()
|
attributes["data-end-time"] = endTime.toString()
|
||||||
|
|
||||||
if (startTime >= now.time) {
|
if (startTime >= nowLocale) {
|
||||||
+"Start in ${formatTimeDiff(startTime - now.time)}"
|
+"Start ${formatTimeDiff(startTime, nowLocale)}"
|
||||||
} else {
|
} else {
|
||||||
+"Ende in ${formatTimeDiff(endTime - now.time)}"
|
+"Ende ${formatTimeDiff(endTime, nowLocale)}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +134,17 @@ fun Route.board() {
|
||||||
div("board-schedule-room") {
|
div("board-schedule-room") {
|
||||||
+schedule.room.name
|
+schedule.room.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div("board-schedule-clock") {
|
||||||
|
i("material-icons") { +"alarm" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div("board-logo") {
|
div("board-logo") {
|
||||||
img("KIF 47.0", "/static/images/logo.svg")
|
img("KIF 47.0", "/static/images/logo.svg")
|
||||||
div("board-header-date") {
|
div("board-header-date") {
|
||||||
attributes["data-now"] =
|
attributes["data-now"] = (now.time - timeOffset).toString()
|
||||||
(now.time - 2 * 60 * 60 * 1000).toString()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
package de.kif.backend.route
|
package de.kif.backend.route
|
||||||
|
|
||||||
import de.kif.backend.Configuration
|
import de.kif.backend.*
|
||||||
import de.kif.backend.Resources
|
|
||||||
import de.kif.backend.authenticateOrRedirect
|
|
||||||
import de.kif.backend.isAuthenticated
|
|
||||||
import de.kif.backend.repository.PostRepository
|
import de.kif.backend.repository.PostRepository
|
||||||
import de.kif.backend.util.markdownToHtml
|
import de.kif.backend.util.markdownToHtml
|
||||||
import de.kif.backend.view.MainTemplate
|
|
||||||
import de.kif.backend.view.MenuTemplate
|
|
||||||
import de.kif.backend.view.respondMain
|
import de.kif.backend.view.respondMain
|
||||||
import de.kif.common.formatDateTime
|
import de.kif.common.formatDateTime
|
||||||
import de.kif.common.model.Permission
|
import de.kif.common.model.Permission
|
||||||
import de.kif.common.model.Post
|
import de.kif.common.model.Post
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.html.respondHtmlTemplate
|
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.http.content.PartData
|
import io.ktor.http.content.PartData
|
||||||
import io.ktor.http.content.forEachPart
|
import io.ktor.http.content.forEachPart
|
||||||
|
@ -26,7 +20,6 @@ import io.ktor.routing.get
|
||||||
import io.ktor.routing.post
|
import io.ktor.routing.post
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import de.kif.backend.prefix
|
|
||||||
|
|
||||||
fun DIV.createPost(post: Post, editable: Boolean = false, additionalClasses: String = "") {
|
fun DIV.createPost(post: Post, editable: Boolean = false, additionalClasses: String = "") {
|
||||||
var classes = "post"
|
var classes = "post"
|
||||||
|
@ -80,6 +73,13 @@ fun Route.overview() {
|
||||||
|
|
||||||
respondMain { theme ->
|
respondMain { theme ->
|
||||||
content {
|
content {
|
||||||
|
if (editable) {
|
||||||
|
div("overview-new") {
|
||||||
|
a("post/new", classes = "form-btn") {
|
||||||
|
+"Neuer Eintrag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
div("overview") {
|
div("overview") {
|
||||||
div("overview-main") {
|
div("overview-main") {
|
||||||
for (post in postList) {
|
for (post in postList) {
|
||||||
|
@ -87,16 +87,10 @@ fun Route.overview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div("overview-side") {
|
div("overview-side") {
|
||||||
if (editable) {
|
|
||||||
div("overview-new") {
|
|
||||||
a("post/new", classes = "form-btn") {
|
|
||||||
+"Neuer Eintrag"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
div("overview-twitter") {
|
div("overview-twitter") {
|
||||||
unsafe {
|
unsafe {
|
||||||
raw("""
|
raw(
|
||||||
|
"""
|
||||||
<a
|
<a
|
||||||
class="twitter-timeline"
|
class="twitter-timeline"
|
||||||
href="${Configuration.Twitter.timeline}"
|
href="${Configuration.Twitter.timeline}"
|
||||||
|
@ -108,7 +102,8 @@ fun Route.overview() {
|
||||||
data-dnt="true"
|
data-dnt="true"
|
||||||
>Twitter wall</a>
|
>Twitter wall</a>
|
||||||
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ database = "data/portal.db"
|
||||||
|
|
||||||
[schedule]
|
[schedule]
|
||||||
reference = "1970-01-01"
|
reference = "1970-01-01"
|
||||||
|
offset = 0
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
session_name = "SESSION"
|
session_name = "SESSION"
|
||||||
|
|
Loading…
Reference in a new issue