Web admin app loads list of players
This commit is contained in:
@@ -5,3 +5,4 @@ plugins {
|
||||
alias(libs.plugins.ktor) apply false
|
||||
alias(libs.plugins.kotlin.serialization) apply false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KotlinProject</title>
|
||||
<link type="text/css" rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body style="text-align: center; align-content: center">
|
||||
<h1>Web Client HTML</h1>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 50 50" role="presentation">
|
||||
<circle cx="25" cy="25" r="20" stroke="#ccc" stroke-width="4" fill="none"/>
|
||||
<circle cx="25" cy="25" r="20" stroke="#333" stroke-width="4" fill="none" stroke-linecap="round"
|
||||
stroke-dasharray="90 125">
|
||||
<animateTransform attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="1s"
|
||||
repeatCount="indefinite"/>
|
||||
</circle>
|
||||
</svg>
|
||||
<script type="application/javascript" src="web.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,6 +3,7 @@ package dev.geekback.dopewars.desktop
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.geekback.dopewars.shared.ApiClient
|
||||
import dev.geekback.dopewars.shared.Player
|
||||
import dev.geekback.dopewars.shared.api.TravelRequest
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ kotlin {
|
||||
commonMain.dependencies {
|
||||
implementation(libs.kotlinx.serialization)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
implementation(libs.ktor.serialization.kotlinx.json)
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.cio)
|
||||
implementation(libs.ktor.client.content.negotiation)
|
||||
}
|
||||
|
||||
wasmJsMain.dependencies {
|
||||
|
||||
+1
-6
@@ -1,11 +1,7 @@
|
||||
package dev.geekback.dopewars.desktop
|
||||
package dev.geekback.dopewars.shared
|
||||
|
||||
import dev.geekback.dopewars.shared.Location
|
||||
import dev.geekback.dopewars.shared.Market
|
||||
import dev.geekback.dopewars.shared.Player
|
||||
import dev.geekback.dopewars.shared.api.PlayerNameUpdateRequest
|
||||
import dev.geekback.dopewars.shared.api.TravelRequest
|
||||
import dev.geekback.dopewars.shared.api.TravelResult
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
@@ -13,7 +9,6 @@ import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.contentType
|
||||
@@ -4,12 +4,15 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
+12
-4
@@ -16,11 +16,19 @@ kotlin {
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(project(":shared"))
|
||||
implementation(project(":shared_ui"))
|
||||
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
implementation(compose.ui)
|
||||
// UI Elements
|
||||
implementation(libs.compose.runtime)
|
||||
implementation(libs.compose.foundation)
|
||||
implementation(libs.compose.material3)
|
||||
implementation(libs.compose.ui)
|
||||
|
||||
// HTTP Client
|
||||
implementation(libs.ktor.serialization.kotlinx.json)
|
||||
implementation(libs.ktor.client.core)
|
||||
// implementation(libs.ktor.client.cio)
|
||||
implementation(libs.ktor.client.content.negotiation)
|
||||
}
|
||||
|
||||
wasmJsMain.dependencies {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.geekback.dopewars.web
|
||||
|
||||
import dev.geekback.dopewars.shared.Player
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.contentType
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
object AdminApi {
|
||||
var baseUrl: String = "http://localhost:8080"
|
||||
private val client = HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(
|
||||
Json {
|
||||
allowSpecialFloatingPointValues = true
|
||||
ignoreUnknownKeys = true
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun setBaseUrl(baseUrl: String) {
|
||||
this.baseUrl = baseUrl
|
||||
}
|
||||
|
||||
suspend fun loadPlayers(): List<Player> {
|
||||
val response = this.client.get("${this.baseUrl}/players") {
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
|
||||
return response.body()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.geekback.dopewars.web
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
|
||||
@Composable
|
||||
fun ApiControlBox(onUrlUpdate: (String) -> Unit) {
|
||||
var localUrl by remember { mutableStateOf("http://localhost:8080") }
|
||||
|
||||
var visible by remember { mutableStateOf(true) }
|
||||
|
||||
Card {
|
||||
Column {
|
||||
Button(onClick = {
|
||||
visible != visible
|
||||
}) {
|
||||
Text("API Config")
|
||||
}
|
||||
TextField(value = AdminApi.baseUrl, onValueChange = {
|
||||
localUrl = it
|
||||
})
|
||||
Button(onClick = {
|
||||
onUrlUpdate(localUrl)
|
||||
}) {
|
||||
Text("Apply")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.geekback.dopewars.web
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.geekback.dopewars.shared.Player
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun App() {
|
||||
val scope = rememberCoroutineScope()
|
||||
var players by mutableStateOf (listOf<Player>())
|
||||
MaterialTheme {
|
||||
Scaffold(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
content = {
|
||||
Column {
|
||||
// List of current Players
|
||||
Button(onClick = {
|
||||
println("Reload Players Now")
|
||||
scope.launch {
|
||||
players = AdminApi.loadPlayers()
|
||||
}
|
||||
}) {
|
||||
Text("Reload Players")
|
||||
}
|
||||
|
||||
ApiControlBox {
|
||||
println("Setting API BaseUrl to $it")
|
||||
AdminApi.setBaseUrl(it)
|
||||
}
|
||||
|
||||
PlayersList(players) {
|
||||
println("Click on $it")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.geekback.dopewars.web
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import dev.geekback.dopewars.shared.Player
|
||||
|
||||
@Composable
|
||||
fun PlayersList(players: List<Player>, onPLayerSelected: (Player) -> Unit) {
|
||||
Card {
|
||||
Text("Current Players")
|
||||
LazyColumn {
|
||||
if (players.isEmpty()) {
|
||||
items(1) {
|
||||
Text("No Players.")
|
||||
}
|
||||
} else {
|
||||
items(players.size) { i ->
|
||||
val item = players[i];
|
||||
Text("Player ${item.name}", modifier = Modifier.clickable { onPLayerSelected(item) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
package dev.geekback.dopewars.web
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.ComposeViewport
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@@ -15,10 +9,3 @@ fun main() {
|
||||
App()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun App() {
|
||||
MaterialTheme {
|
||||
Text(modifier = Modifier.padding(16.dp), text = "Taxation is theft")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user