Remove websockets

This commit is contained in:
Lars Westermann 2019-06-11 10:36:12 +02:00
parent 8f8242a97a
commit 7b7a9b0fc2
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
17 changed files with 196 additions and 123 deletions

View file

@ -1,68 +1,92 @@
package de.kif.frontend
import de.kif.common.Message
import de.kif.common.MessageBox
import de.kif.common.MessageType
import de.kif.common.RepositoryType
import de.kif.frontend.repository.*
import de.westermann.kwebview.async
import org.w3c.dom.MessageEvent
import org.w3c.dom.WebSocket
import org.w3c.dom.events.Event
import de.westermann.kwebview.clearInterval
import de.westermann.kwebview.createHtmlView
import de.westermann.kwebview.interval
import kotlinx.serialization.DynamicObjectParser
import org.w3c.dom.get
import org.w3c.xhr.XMLHttpRequest
import kotlin.browser.document
import kotlin.browser.window
class WebSocketClient() {
class WebSocketClient {
private val prefix = js("prefix")
private val url = "$prefix/api/updates"
private val body = document.body ?: createHtmlView()
private val parser = DynamicObjectParser()
private val useSsl = "https" in window.location.protocol
private val wsProtocol = if (useSsl) "wss" else "ws"
private val url = "$wsProtocol://${window.location.host}$prefix/websocket"
private var timestamp = body.dataset["timestamp"]?.toLongOrNull() ?: 0L
private var intervalId: Int? = null
private lateinit var ws: WebSocket
private var reconnect = false
private fun reload() {
val id = intervalId ?: return
clearInterval(id)
intervalId = null
@Suppress("UNUSED_PARAMETER")
private fun onOpen(event: Event) {
console.log("Connected!")
if (reconnect) {
window.location.reload()
}
window.location.reload()
}
private fun onMessage(messageEvent: MessageEvent) {
val message = Message.parse(messageEvent.data?.toString() ?: "")
private fun onMessage(messageBox: MessageBox) {
body.classList.remove("offline")
for (handler in messageHandlers) {
if (handler.repository == message.repository) {
when (message.type) {
MessageType.CREATE -> handler.onCreate(message.id)
MessageType.UPDATE -> handler.onUpdate(message.id)
MessageType.DELETE -> handler.onDelete(message.id)
if (messageBox.valid) {
timestamp = messageBox.timestamp
for (message in messageBox.messages) {
for (handler in messageHandlers) {
if (handler.repository == message.repository) {
when (message.type) {
MessageType.CREATE -> handler.onCreate(message.id)
MessageType.UPDATE -> handler.onUpdate(message.id)
MessageType.DELETE -> handler.onDelete(message.id)
}
}
}
}
} else {
reload()
}
}
@Suppress("UNUSED_PARAMETER")
private fun onClose(event: Event) {
console.log("Disconnected!")
reconnect = true
async(1000) {
connect()
private fun onError(code: Int) {
if (!body.classList.contains("offline")) {
console.log("Offline reason: $code")
}
body.classList.add("offline")
}
@Suppress("UNUSED_PARAMETER")
private fun onError(event: Event) {
console.log("An error occurred!")
}
private fun request() {
val xmlHttpRequest = XMLHttpRequest()
private fun connect() {
ws = WebSocket(url)
xmlHttpRequest.onreadystatechange = {
try {
if (xmlHttpRequest.readyState == 4.toShort()) {
if (xmlHttpRequest.status == 200.toShort() || xmlHttpRequest.status == 304.toShort()) {
val json = JSON.parse<JsonResponse>(xmlHttpRequest.responseText)
ws.onopen = this::onOpen
ws.onmessage = this::onMessage
ws.onclose = this::onClose
ws.onerror = this::onError
if (json.OK) {
val message = parser.parse(json.data, MessageBox.serializer())
onMessage(message)
} else {
onError(-1)
}
} else {
onError(xmlHttpRequest.status.toInt())
}
}
} catch (e: Exception) {
console.error(e)
onError(-2)
}
}
xmlHttpRequest.open("GET", "$url?timestamp=$timestamp", true)
xmlHttpRequest.overrideMimeType("application/json")
xmlHttpRequest.send()
}
private val messageHandlers: List<MessageHandler> = listOf(
@ -75,7 +99,9 @@ class WebSocketClient() {
)
init {
connect()
intervalId = interval(500) {
request()
}
}
}

View file

@ -8,10 +8,15 @@ import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.js.Promise
interface JsonResponse {
val OK: Boolean
val data: dynamic
}
suspend fun repositoryGet(
url: String
): dynamic {
val promise = Promise<dynamic> { resolve, reject ->
val promise = Promise<JsonResponse> { resolve, reject ->
val xhttp = XMLHttpRequest()
xhttp.onreadystatechange = {
@ -47,7 +52,7 @@ suspend fun repositoryPost(
url: String,
data: String? = null
): dynamic {
val promise = Promise<dynamic> { resolve, reject ->
val promise = Promise<JsonResponse> { resolve, reject ->
val xhttp = XMLHttpRequest()
xhttp.onreadystatechange = {

View file

@ -3,6 +3,7 @@ package de.kif.frontend.repository
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.Post
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -25,13 +26,13 @@ object PostRepository : Repository<Post> {
}
override suspend fun create(model: Post): Long {
return repositoryPost("$prefix/api/posts", Message.json.stringify(Post.serializer(), model))
return repositoryPost("$prefix/api/posts", Serialization.stringify(Post.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: Post) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/post/${model.id}", Message.json.stringify(Post.serializer(), model))
repositoryPost("$prefix/api/post/${model.id}", Serialization.stringify(Post.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -3,6 +3,7 @@ package de.kif.frontend.repository
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.Room
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -25,13 +26,13 @@ object RoomRepository : Repository<Room> {
}
override suspend fun create(model: Room): Long {
return repositoryPost("$prefix/api/rooms", Message.json.stringify(Room.serializer(), model))
return repositoryPost("$prefix/api/rooms", Serialization.stringify(Room.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: Room) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/room/${model.id}", Message.json.stringify(Room.serializer(), model))
repositoryPost("$prefix/api/room/${model.id}", Serialization.stringify(Room.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -1,9 +1,6 @@
package de.kif.frontend.repository
import de.kif.common.ConstraintMap
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.*
import de.kif.common.model.Schedule
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -31,13 +28,13 @@ object ScheduleRepository : Repository<Schedule> {
}
override suspend fun create(model: Schedule): Long {
return repositoryPost("$prefix/api/schedules", Message.json.stringify(Schedule.serializer(), model))
return repositoryPost("$prefix/api/schedules", Serialization.stringify(Schedule.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: Schedule) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/schedule/${model.id}", Message.json.stringify(Schedule.serializer(), model))
repositoryPost("$prefix/api/schedule/${model.id}", Serialization.stringify(Schedule.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -3,6 +3,7 @@ package de.kif.frontend.repository
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.Track
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -25,13 +26,13 @@ object TrackRepository : Repository<Track> {
}
override suspend fun create(model: Track): Long {
return repositoryPost("$prefix/api/tracks", Message.json.stringify(Track.serializer(), model))
return repositoryPost("$prefix/api/tracks", Serialization.stringify(Track.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: Track) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/track/${model.id}", Message.json.stringify(Track.serializer(), model))
repositoryPost("$prefix/api/track/${model.id}", Serialization.stringify(Track.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -3,6 +3,7 @@ package de.kif.frontend.repository
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.User
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -25,13 +26,13 @@ object UserRepository : Repository<User> {
}
override suspend fun create(model: User): Long {
return repositoryPost("$prefix/api/users", Message.json.stringify(User.serializer(), model))
return repositoryPost("$prefix/api/users", Serialization.stringify(User.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: User) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/user/${model.id}", Message.json.stringify(User.serializer(), model))
repositoryPost("$prefix/api/user/${model.id}", Serialization.stringify(User.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -3,6 +3,7 @@ package de.kif.frontend.repository
import de.kif.common.Message
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.WorkGroup
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
@ -25,13 +26,13 @@ object WorkGroupRepository : Repository<WorkGroup> {
}
override suspend fun create(model: WorkGroup): Long {
return repositoryPost("$prefix/api/workgroups", Message.json.stringify(WorkGroup.serializer(), model))
return repositoryPost("$prefix/api/workgroups", Serialization.stringify(WorkGroup.serializer(), model))
?: throw IllegalStateException("Cannot create model!")
}
override suspend fun update(model: WorkGroup) {
if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
repositoryPost("$prefix/api/workgroup/${model.id}", Message.json.stringify(WorkGroup.serializer(), model))
repositoryPost("$prefix/api/workgroup/${model.id}", Serialization.stringify(WorkGroup.serializer(), model))
}
override suspend fun delete(id: Long) {

View file

@ -58,7 +58,7 @@
width: 100%;
height: 100%;
border-bottom: solid 1px var(--table-border-color);
box-shadow: 0 0 4px black;
box-shadow: 0 0 4px var(--shadow-color);
top: -1rem;
padding-top: 1.2rem;
}

View file

@ -160,3 +160,25 @@ a {
}
}
}
.offline-banner {
position: fixed;
bottom: 3rem;
left: 0;
right: 0;
height: 3rem;
line-height: 3rem;
text-align: center;
font-size: 1.2rem;
background-color: var(--primary-color);
color: var(--primary-text-color);
z-index: 12;
box-shadow: 0 1px 4px var(--shadow-color);
display: none;
}
body.offline {
.offline-banner {
display: block;
}
}