diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt
index fd2b1b4..f745c8e 100644
--- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt
+++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt
@@ -16,6 +16,7 @@ object PairingHandler: PairgothApiHandler {
override fun get(request: HttpServletRequest, response: HttpServletResponse): Json? {
val tournament = getTournament(request)
val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number")
+ if (round > tournament.lastRound() + 1) badRequest("invalid round: previous round has not been played")
val playing = tournament.games(round).values.flatMap {
listOf(it.black, it.white)
}.toSet()
diff --git a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/ApiTool.kt b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/ApiTool.kt
index 41c4268..dabcb33 100644
--- a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/ApiTool.kt
+++ b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/ApiTool.kt
@@ -6,25 +6,37 @@ import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.internal.EMPTY_REQUEST
+import org.slf4j.LoggerFactory
class ApiTool {
companion object {
const val JSON = "application/json"
val apiRoot = System.getProperty("pairgoth.api.external.url")?.let { "${it.removeSuffix("/")}/" }
?: throw Error("no configured API url")
+ val logger = LoggerFactory.getLogger("api")
}
private val client = OkHttpClient()
private fun prepare(url: String) = Request.Builder().url("$apiRoot$url").header("Accept", JSON)
private fun Json.toRequestBody() = toString().toRequestBody(JSON.toMediaType())
private fun Request.Builder.process(): Json {
- client.newCall(build()).execute().use { response ->
- if (response.isSuccessful) {
- when (response.body?.contentType()?.subtype) {
- null -> throw Error("null body or content type")
- "json" -> return Json.parse(response.body!!.string()) ?: throw Error("could not parse json")
- else -> throw Error("unhandled content type: ${response.body!!.contentType()}")
+ try {
+ return client.newCall(build()).execute().use { response ->
+ if (response.isSuccessful) {
+ when (response.body?.contentType()?.subtype) {
+ null -> throw Error("null body or content type")
+ "json" -> Json.parse(response.body!!.string()) ?: throw Error("could not parse json")
+ else -> throw Error("unhandled content type: ${response.body!!.contentType()}")
+ }
+ } else {
+ when (response.body?.contentType()?.subtype) {
+ "json" -> Json.parse(response.body!!.string()) ?: throw Error("could not parse error json")
+ else -> throw Error("${response.code} ${response.message}")
+ }
}
- } else throw Error("api call failed: ${response.code} ${response.message}")
+ }
+ } catch (e: Throwable) {
+ logger.error("api call failed", e)
+ return Json.Object("error" to e.message)
}
}
diff --git a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/PairgothTool.kt b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/PairgothTool.kt
new file mode 100644
index 0000000..75a0abf
--- /dev/null
+++ b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/view/PairgothTool.kt
@@ -0,0 +1,11 @@
+package org.jeudego.pairgoth.view
+
+import com.republicate.kson.Json
+
+/**
+ * Generic utilities
+ */
+
+class PairgothTool {
+ public fun toMap(array: Json.Array) = array.map { ser -> ser as Json.Object }.associateBy { it.getLong("id")!! }
+}
\ No newline at end of file
diff --git a/view-webapp/src/main/sass/tour.scss b/view-webapp/src/main/sass/tour.scss
index 684af4a..7e057e0 100644
--- a/view-webapp/src/main/sass/tour.scss
+++ b/view-webapp/src/main/sass/tour.scss
@@ -164,7 +164,7 @@
max-width: 40vw;
border: solid 2px darkgray;
border-radius: 5px;
- padding-top: 1em;
+ padding: 1em 0.5em;
&:before {
position: absolute;
content: attr(title);
@@ -175,6 +175,21 @@
font-size: smaller;
font-weight: bold;
}
+ .listitem {
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-between;
+ gap: 1em;
+ cursor: pointer;
+ user-select: none;
+ &:hover {
+ background-color: rgba(50, 50, 50, .2);
+ }
+ &.selected {
+ background-color: rgba(100,200,255,200);
+ cursor: grab;
+ }
+ }
}
#pairing-buttons {
display: flex;
diff --git a/view-webapp/src/main/webapp/WEB-INF/tools.xml b/view-webapp/src/main/webapp/WEB-INF/tools.xml
index 811a5d3..6d68015 100644
--- a/view-webapp/src/main/webapp/WEB-INF/tools.xml
+++ b/view-webapp/src/main/webapp/WEB-INF/tools.xml
@@ -4,13 +4,14 @@
+
-
+Exception