Ping Frontend Desktop und WasmJs funktionieren
This commit is contained in:
@@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
alias(libs.plugins.compose.multiplatform)
|
||||
alias(libs.plugins.compose.compiler)
|
||||
}
|
||||
@@ -28,6 +29,13 @@ kotlin {
|
||||
implementation(compose.ui)
|
||||
implementation(compose.components.resources)
|
||||
implementation(compose.components.uiToolingPreview)
|
||||
|
||||
// HTTP client dependencies for ping-service
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.contentNegotiation)
|
||||
implementation(libs.ktor.client.serialization.kotlinx.json)
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
}
|
||||
commonTest.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
@@ -35,6 +43,10 @@ kotlin {
|
||||
jvmMain.dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(libs.kotlinx.coroutines.swing)
|
||||
implementation(libs.ktor.client.cio)
|
||||
}
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,41 +4,51 @@
|
||||
android:width="450dp"
|
||||
android:height="450dp"
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<path
|
||||
android:pathData="M56.25,18V46L32,60 7.75,46V18L32,4Z"
|
||||
android:fillColor="#6075f2"/>
|
||||
<path
|
||||
android:pathData="m41.5,26.5v11L32,43V60L56.25,46V18Z"
|
||||
android:fillColor="#6b57ff"/>
|
||||
<path
|
||||
android:pathData="m32,43 l-9.5,-5.5v-11L7.75,18V46L32,60Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="23.131"
|
||||
android:centerY="18.441"
|
||||
android:gradientRadius="42.132"
|
||||
android:type="radial">
|
||||
<item android:offset="0" android:color="#FF5383EC"/>
|
||||
<item android:offset="0.867" android:color="#FF7F52FF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M22.5,26.5 L32,21 41.5,26.5 56.25,18 32,4 7.75,18Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="44.172"
|
||||
android:startY="4.377"
|
||||
android:endX="17.973"
|
||||
android:endY="34.035"
|
||||
android:type="linear">
|
||||
<item android:offset="0" android:color="#FF33C3FF"/>
|
||||
<item android:offset="0.878" android:color="#FF5383EC"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="m32,21 l9.526,5.5v11L32,43 22.474,37.5v-11z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
android:viewportHeight="64"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://schemas.android.com/aapt ">
|
||||
<path
|
||||
android:pathData="M56.25,18V46L32,60 7.75,46V18L32,4Z"
|
||||
android:fillColor="#6075f2"/>
|
||||
<path
|
||||
android:pathData="m41.5,26.5v11L32,43V60L56.25,46V18Z"
|
||||
android:fillColor="#6b57ff"/>
|
||||
<path
|
||||
android:pathData="m32,43 l-9.5,-5.5v-11L7.75,18V46L32,60Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="23.131"
|
||||
android:centerY="18.441"
|
||||
android:gradientRadius="42.132"
|
||||
android:type="radial">
|
||||
<item
|
||||
android:offset="0"
|
||||
android:color="#FF5383EC"/>
|
||||
<item
|
||||
android:offset="0.867"
|
||||
android:color="#FF7F52FF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M22.5,26.5 L32,21 41.5,26.5 56.25,18 32,4 7.75,18Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="44.172"
|
||||
android:startY="4.377"
|
||||
android:endX="17.973"
|
||||
android:endY="34.035"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:offset="0"
|
||||
android:color="#FF33C3FF"/>
|
||||
<item
|
||||
android:offset="0.878"
|
||||
android:color="#FF5383EC"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="m32,21 l9.526,5.5v11L32,43 22.474,37.5v-11z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
|
||||
@@ -7,20 +7,66 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeContentPadding
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.plugins.contentnegotiation.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PingResponse(
|
||||
val status: String,
|
||||
val timestamp: String? = null,
|
||||
val message: String? = null
|
||||
)
|
||||
|
||||
sealed class PingState {
|
||||
object Idle : PingState()
|
||||
object Loading : PingState()
|
||||
data class Success(val response: PingResponse) : PingState()
|
||||
data class Error(val message: String) : PingState()
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun App() {
|
||||
MaterialTheme {
|
||||
var showContent by remember { mutableStateOf(false) }
|
||||
var pingState by remember { mutableStateOf<PingState>(PingState.Idle) }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
// Create HTTP client
|
||||
val httpClient = remember {
|
||||
HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup client on disposal
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
httpClient.close()
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
@@ -35,6 +81,7 @@ fun App() {
|
||||
modifier = Modifier.padding(top = 32.dp, bottom = 16.dp)
|
||||
)
|
||||
|
||||
// Platform Info Button
|
||||
Button(
|
||||
onClick = { showContent = !showContent },
|
||||
modifier = Modifier.padding(16.dp)
|
||||
@@ -42,6 +89,91 @@ fun App() {
|
||||
Text(if (showContent) "Platform-Info ausblenden" else "Platform-Info anzeigen")
|
||||
}
|
||||
|
||||
// Ping Backend Button
|
||||
Button(
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
pingState = PingState.Loading
|
||||
try {
|
||||
val response: PingResponse = httpClient.get("http://localhost:8082/ping").body()
|
||||
pingState = PingState.Success(response)
|
||||
} catch (e: Exception) {
|
||||
pingState = PingState.Error(e.message ?: "Unknown error occurred")
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled = pingState !is PingState.Loading,
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
if (pingState is PingState.Loading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.height(16.dp),
|
||||
color = MaterialTheme.colorScheme.onPrimary
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
Text("Ping Backend")
|
||||
}
|
||||
|
||||
// Ping Status Display
|
||||
when (val state = pingState) {
|
||||
is PingState.Success -> {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "✅ Ping erfolgreich!",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = Color(0xFF4CAF50)
|
||||
)
|
||||
Text(
|
||||
text = "Status: ${state.response.status}",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(top = 4.dp)
|
||||
)
|
||||
state.response.timestamp?.let {
|
||||
Text(
|
||||
text = "Zeit: $it",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(top = 2.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is PingState.Error -> {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "❌ Ping fehlgeschlagen",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = Color(0xFFF44336)
|
||||
)
|
||||
Text(
|
||||
text = "Fehler: ${state.message}",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(top = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// Idle or Loading state - no additional display needed
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(showContent) {
|
||||
val greeting = remember { Greeting().greet() }
|
||||
Column(
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package at.mocode.temp.pingservice
|
||||
|
||||
import org.springframework.web.bind.annotation.CrossOrigin
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@CrossOrigin(origins = ["http://localhost:8080"])
|
||||
class PingController(
|
||||
private val pingService: PingServiceCircuitBreaker
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user