Hard reload for info beamer

This commit is contained in:
Lars Westermann 2019-06-13 06:45:07 +02:00
parent e8f816e7ec
commit 664f9c1777
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
16 changed files with 134 additions and 35 deletions

View file

@ -90,6 +90,7 @@ kotlin {
implementation "io.ktor:ktor-client-apache:$ktor_version"
implementation 'org.xerial:sqlite-jdbc:3.25.2'
api 'mysql:mysql-connector-java:8.0.16'
implementation 'org.jetbrains.exposed:exposed:0.12.2'
implementation 'org.mindrot:jbcrypt:0.4'

View file

@ -18,3 +18,9 @@ wiki_url = "https://wiki.kif.rocks/w/index.php?title=KIF470:Arbeitskreise&action
[twitter]
timeline = "https://twitter.com/kiforbiter?ref_src=twsrc%5Etfw"
[database]
type = "sqlite"
url = ""
username = ""
password = ""

View file

@ -1,5 +1,8 @@
package de.kif.frontend
import de.kif.frontend.repository.RoomRepository
import de.kif.frontend.repository.ScheduleRepository
import de.kif.frontend.repository.WorkGroupRepository
import de.kif.frontend.views.board.initBoard
import de.kif.frontend.views.calendar.initCalendar
import de.kif.frontend.views.initAnnouncement
@ -61,4 +64,35 @@ fun main() = init {
}
}
}
val url = window.location.pathname
if ("brett" in url || "wand" in url) {
ScheduleRepository.onCreate {
window.location.reload()
}
ScheduleRepository.onUpdate {
window.location.reload()
}
ScheduleRepository.onDelete {
window.location.reload()
}
RoomRepository.onCreate {
window.location.reload()
}
RoomRepository.onUpdate {
window.location.reload()
}
RoomRepository.onDelete {
window.location.reload()
}
WorkGroupRepository.onCreate {
window.location.reload()
}
WorkGroupRepository.onUpdate {
window.location.reload()
}
WorkGroupRepository.onDelete {
window.location.reload()
}
}
}

View file

@ -26,11 +26,12 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
private val htmlBody = document.body ?: createHtmlView()
val day = (calendarTable.dataset["day"]?.toIntOrNull() ?: -1).also { println(it) }
val reloadOnFinish = (calendarTable.dataset["reload"]?.toBoolean() ?: false).also { println(it) }
val referenceDate = (calendarTable.dataset["reference"]?.toLongOrNull() ?: -1L).also { println(it) }
val nowDate = (calendarTable.dataset["now"]?.toLongOrNull() ?: -1L).also { println(it) }
val timeDifference = (Date.now().toLong() - nowDate).also { println(it) }
val day = (calendarTable.dataset["day"]?.toIntOrNull() ?: -1)
val reloadOnFinish = (calendarTable.dataset["reload"]?.toBoolean() ?: false)
val hideEmpty = (calendarTable.dataset["hide-empty"]?.toBoolean() ?: false)
val referenceDate = (calendarTable.dataset["reference"]?.toLongOrNull() ?: -1L)
val nowDate = (calendarTable.dataset["now"]?.toLongOrNull() ?: -1L)
val timeDifference = (Date.now().toLong() - nowDate)
fun scrollVerticalBy(pixel: Double, scrollBehavior: ScrollBehavior = ScrollBehavior.SMOOTH) {
scrollAllVerticalBy(pixel, scrollBehavior)

View file

@ -74,18 +74,12 @@ class CalendarBody(val calendar: Calendar, view: HTMLElement) : ViewCollection<C
min = (min / 60 - 1) * 60
max = (max / 60 + 2) * 60
if (min == minTime && max == maxTime) return
minTime = min
maxTime = max
min = calendarBodies.map { it.minTime }.min() ?: min
max = calendarBodies.map { it.maxTime }.max() ?: max
calendarBodies.filter { it != this }.forEach {
it.updateRows()
}
while (isNotEmpty() && min > first().time) {
remove(first())
}

View file

@ -8,7 +8,7 @@ import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLSpanElement
import org.w3c.dom.set
class CalendarRow(calendar: CalendarBody, view: HTMLElement) : ViewCollection<CalendarCell>(view) {
class CalendarRow(val calendar: CalendarBody, view: HTMLElement) : ViewCollection<CalendarCell>(view) {
val day = calendar.day
val time = dataset["time"]?.toIntOrNull() ?: 0
@ -49,8 +49,6 @@ class CalendarRow(calendar: CalendarBody, view: HTMLElement) : ViewCollection<Ca
}
row.html.appendChild(rowHeader)
row.html
val rooms = RoomRepository.all()
for (room in rooms) {

View file

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

View file

@ -133,6 +133,20 @@ object Configuration {
val time by c(ResoSpec.time)
}
private object DatabaseSpec : ConfigSpec("database") {
val type by required<String>()
val url by required<String>()
val username by required<String>()
val password by required<String>()
}
object Database {
val type by c(DatabaseSpec.type)
val url by c(DatabaseSpec.url)
val username by c(DatabaseSpec.username)
val password by c(DatabaseSpec.password)
}
init {
var config = Config {
addSpec(ServerSpec)
@ -142,6 +156,7 @@ object Configuration {
addSpec(GeneralSpec)
addSpec(TwitterSpec)
addSpec(ResoSpec)
addSpec(DatabaseSpec)
}.from.toml.resource("portal.toml")
for (file in Files.list(Paths.get("."))) {

View file

@ -26,14 +26,39 @@ object Connection {
)
fun init() {
val dbPath = Configuration.Path.databasePath.toString()
Database.connect("jdbc:sqlite:$dbPath", "org.sqlite.JDBC")
val type = Configuration.Database.type
val url = Configuration.Database.url
val username = Configuration.Database.username
val password = Configuration.Database.password
when (type) {
"mysql" -> {
Database.connect(
"jdbc:mysql://$url:3306/akplan?user=$username&password=$password&serverTimezone=UTC",
"com.mysql.cj.jdbc.Driver",
username,
password
)
}
"mariadb" -> {
Database.connect(
"jdbc:mariadb://$url:3306/akplan?user=$username&password=$password&serverTimezone=UTC",
"org.mariadb.jdbc.Driver",
username,
password
)
}
else -> {
val dbPath = Configuration.Path.databasePath.toString()
Database.connect("jdbc:sqlite:$dbPath", "org.sqlite.JDBC")
}
}
TransactionManager.manager.defaultIsolationLevel = TRANSACTION_SERIALIZABLE
try {
create()
} catch (e: ExposedSQLException) {
logger.error { "Cannot initialize the database!" }
logger.error(e) { "Cannot initialize the database!" }
print("Do you want to recreate the database (you will lose all data)? [y/N]: ")
val result = readLine()

View file

@ -29,7 +29,7 @@ object DbWorkGroup : Table() {
val accessible = bool("accessible")
val language = enumeration("language", Language::class)
val leader = text("leader").default("[]")
val leader = text("leader")
val length = integer("length")
val constraints = text("constraints")
@ -49,9 +49,9 @@ object DbRoom : Table() {
val whiteboard = bool("whiteboard")
val blackboard = bool("blackboard")
val accessible = bool("accessible")
val pool = bool("pool").default(false)
val pool = bool("pool")
val blocked = text("blocked").default("[]")
val blocked = text("blocked")
val createdAt = long("createdAt")
val updatedAt = long("updatedAt")
@ -63,8 +63,8 @@ object DbSchedule : Table() {
val roomId = long("room_id").index()
val day = integer("day").index()
val time = integer("time_slot")
val lockRoom = bool("lock_room").default(false)
val lockTime = bool("lock_time").default(false)
val lockRoom = bool("lock_room")
val lockTime = bool("lock_time")
val createdAt = long("createdAt")
val updatedAt = long("updatedAt")

View file

@ -6,10 +6,12 @@ import de.kif.backend.prefix
import de.kif.backend.repository.*
import de.kif.backend.route.api.error
import de.kif.backend.util.Backup
import de.kif.backend.util.PushService
import de.kif.backend.util.WikiImporter
import de.kif.backend.view.respondMain
import de.kif.common.RepositoryType
import de.kif.common.model.Permission
import de.kif.common.model.Post
import io.ktor.application.call
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
@ -51,6 +53,10 @@ fun Route.account() {
+"Sicherung"
}
a(href = "$prefix/account/reload", classes = "form-btn") {
+"Alle Geräte neu laden"
}
if (user.checkPermission(Permission.SCHEDULE)) {
a(href = "$prefix/account/import", classes = "form-btn") {
+"Aus Wiki importieren"
@ -516,4 +522,8 @@ fun Route.account() {
call.error(HttpStatusCode.Unauthorized)
}
}
get("/account/reload") {
PushService.signature = Post.generateUrl()
call.respondRedirect("$prefix/account")
}
}

View file

@ -175,7 +175,8 @@ fun Route.board() {
max,
rooms,
schedules,
reloadAfterFinish = true
reloadAfterFinish = true,
hideEmptyRooms = true
)
}
div("board-twitter") {

View file

@ -72,7 +72,8 @@ fun DIV.renderCalendar(
to: Int,
rooms: List<Room>,
schedules: Map<Room, Map<Int, List<Schedule>>>,
reloadAfterFinish: Boolean = false
reloadAfterFinish: Boolean = false,
hideEmptyRooms: Boolean = false
) {
val gridLabelWidth = 60
val minutesOfDay = to - from
@ -91,6 +92,7 @@ fun DIV.renderCalendar(
attributes["data-reference"] = Configuration.Schedule.referenceDate.time.toString()
attributes["data-now"] = now.timeInMillis.toString()
attributes["data-reload"] = reloadAfterFinish.toString()
attributes["data-hide-empty"] = hideEmptyRooms.toString()
div("calendar-table-box ${orientation.name.toLowerCase().replace("_", "-")}") {
div("calendar-header") {
@ -103,6 +105,7 @@ fun DIV.renderCalendar(
for (room in rooms) {
div("calendar-cell") {
attributes["data-room"] = room.id.toString()
attributes["data-empty"] = (hideEmptyRooms && room !in schedules).toString()
span {
+room.name
@ -147,6 +150,7 @@ fun DIV.renderCalendar(
div("calendar-cell") {
attributes["data-room"] = room.id.toString()
attributes["data-blocked"] = blocked.toString()
attributes["data-empty"] = (hideEmptyRooms && room !in schedules).toString()
title = room.name + " - " + timeString

View file

@ -1,11 +1,11 @@
package de.kif.backend.route
import com.soywiz.klock.*
import com.soywiz.klock.locale.german
import de.kif.backend.Configuration
import de.kif.backend.repository.RoomRepository
import de.kif.backend.repository.ScheduleRepository
import de.kif.backend.view.respondMain
import de.kif.common.formatDate
import de.kif.common.formatDateWithoutYear
import de.kif.common.model.Room
import de.kif.common.model.Schedule
import io.ktor.routing.Route
@ -63,6 +63,8 @@ fun Route.wall() {
wallStart + 2
).map { genWallData(it) }
val rooms = RoomRepository.all()
var min = days.mapNotNull { it.min }.min() ?: 12 * 60
val max = days.mapNotNull { it.max }.max() ?: 12 * 60
@ -70,18 +72,15 @@ fun Route.wall() {
min = max
}
val refDate = DateTime(Configuration.Schedule.referenceDate.time)
val refDate = Configuration.Schedule.referenceDate.time
respondMain(true, true) {
content {
div("wall") {
for (day in days) {
val date = refDate + day.number.days
val dateString = DateFormat("EEEE, d. MMMM")
.withLocale(KlockLocale.german)
.format(date)
val date = refDate + (day.number * 1000 * 60 * 60 * 24)
val dateString = formatDateWithoutYear(date, Configuration.Schedule.offset)
div("wall-box") {
div("wall-name") {
@ -95,8 +94,9 @@ fun Route.wall() {
day.number,
min,
max,
day.schedules.keys.toList().sortedBy { it.id },
day.schedules
rooms,
day.schedules,
hideEmptyRooms = true
)
}
}

View file

@ -18,7 +18,7 @@ import kotlin.concurrent.thread
object PushService {
internal var leastValidTimestamp = System.currentTimeMillis()
val signature = Post.generateUrl()
var signature = Post.generateUrl()
private val messages: MutableList<Pair<Long, Message>> = mutableListOf()

View file

@ -32,3 +32,9 @@ backup_interval = 3600000
[twitter]
timeline = ""
[database]
type = "sqlite"
url = ""
username = ""
password = ""