Working on data viewer UI

This commit is contained in:
Alexander Nozik 2022-12-06 22:49:02 +03:00
parent 7efb952163
commit e95f73d94d
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
7 changed files with 136 additions and 87 deletions

View File

@ -16,7 +16,7 @@ allprojects {
val dataforgeVersion by extra("0.6.0-dev-15") val dataforgeVersion by extra("0.6.0-dev-15")
val tablesVersion: String by extra("0.2.0-dev-3") val tablesVersion: String by extra("0.2.0-dev-3")
val kmathVersion by extra("0.3.1-dev-6") val kmathVersion by extra("0.3.1-dev-6")
val visionForgeVersion: String by rootProject.extra("0.3.0-dev-4") val visionForgeVersion: String by rootProject.extra("0.3.0-dev-6")
ksciencePublish{ ksciencePublish{

View File

@ -13,3 +13,4 @@ org.gradle.parallel=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
toolsVersion=0.13.3-kotlin-1.7.20 toolsVersion=0.13.3-kotlin-1.7.20
compose.version=1.2.1

View File

@ -1,5 +1,6 @@
plugins { plugins {
id("space.kscience.gradle.mpp") id("space.kscience.gradle.mpp")
id("org.jetbrains.compose")
`maven-publish` `maven-publish`
} }
@ -28,7 +29,14 @@ kotlin {
jvmMain { jvmMain {
dependencies { dependencies {
implementation(project(":numass-data-proto")) implementation(project(":numass-data-proto"))
implementation("space.kscience:visionforge-server:$visionForgeVersion") implementation("io.ktor:ktor-server-cio:2.1.3")
implementation("io.ktor:ktor-server-html-builder-jvm:2.1.3")
implementation("space.kscience:visionforge-plotly:$visionForgeVersion")
}
}
jsMain{
dependencies{
implementation(compose.web.core)
} }
} }

View File

@ -37,7 +37,7 @@ public class NumassJsPlugin : AbstractPlugin(), ElementVisionRenderer {
else -> super.content(target) else -> super.content(target)
} }
override fun render(element: Element, vision: Vision, meta: Meta) { override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
when (vision) { when (vision) {
is VisionOfNumassHv -> element.append { is VisionOfNumassHv -> element.append {
h1 { +"HV" } h1 { +"HV" }
@ -64,7 +64,7 @@ public class NumassJsPlugin : AbstractPlugin(), ElementVisionRenderer {
vision.spectra.forEach { (channel, spectrum) -> vision.spectra.forEach { (channel, spectrum) ->
val pairs = spectrum.entries.sortedBy { it.key } val pairs = spectrum.entries.sortedBy { it.key }
scatter { scatter {
name = channel this.name = channel
mode = ScatterMode.lines mode = ScatterMode.lines
line { line {
shape = LineShape.hv shape = LineShape.hv

View File

@ -0,0 +1,27 @@
package ru.inr.mass.data.server
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.renderComposable
import org.w3c.dom.Document
import space.kscience.dataforge.context.Context
import space.kscience.visionforge.Application
public class NumassViewerApplication : Application {
private val context = Context("NumassViewer") {
plugin(NumassJsPlugin)
}
override fun start(document: Document, state: Map<String, Any>) {
renderComposable(rootElementId = "application") {
Div({ classes("container") }) {
Div({ classes("row") })
Div({ classes("col-md-3") }) {
}
Div({ classes("col-md-9") }) {
}
}
}
}
}

View File

@ -1,15 +1,19 @@
package ru.inr.mass.data.server package ru.inr.mass.data.server
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.http.URLBuilder import io.ktor.server.application.Application
import io.ktor.server.application.call import io.ktor.server.application.call
import io.ktor.server.cio.CIO import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
import io.ktor.server.html.respondHtml
import io.ktor.server.http.content.resources
import io.ktor.server.response.respondText import io.ktor.server.response.respondText
import io.ktor.server.routing.get import io.ktor.server.routing.get
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.html.*
import ru.inr.mass.data.api.NumassPoint import ru.inr.mass.data.api.NumassPoint
import ru.inr.mass.data.proto.NumassDirectorySet import ru.inr.mass.data.proto.NumassDirectorySet
import ru.inr.mass.data.proto.NumassProtoPlugin import ru.inr.mass.data.proto.NumassProtoPlugin
@ -22,12 +26,15 @@ import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.cutLast import space.kscience.dataforge.names.cutLast
import space.kscience.dataforge.names.lastOrNull import space.kscience.dataforge.names.lastOrNull
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionServer
public suspend fun main() { public fun main() {
val port = 7777
val host = "localhost"
embeddedServer(CIO, port, host, module = Application::numassModule).start()
}
public fun Application.numassModule() {
val context = Context("Numass") { val context = Context("Numass") {
plugin(NumassProtoPlugin) plugin(NumassProtoPlugin)
plugin(NumassCommonPlugin) plugin(NumassCommonPlugin)
@ -40,93 +47,98 @@ public suspend fun main() {
val repositroyName = "D:\\Work\\Numass\\data\\test" val repositroyName = "D:\\Work\\Numass\\data\\test"
val port = 7777 val repository: DataTree<NumassDirectorySet> = runBlocking { numassProto.readRepository(repositroyName) }
val host = "localhost"
val url = URLBuilder(host = host, port = port).build() routing {
resources()
val repository: DataTree<NumassDirectorySet> = numassProto.readRepository(repositroyName) get("/") {
call.respondHtml {
val visionOfNumassRepository = VisionOfNumassRepository(Name.EMPTY, repository) head {
meta { charset = "utf-8" }
val server = context.embeddedServer(CIO, port, host) { meta {
routing { name = "viewport"
get("/repository") { content = "width=device-width, initial-scale=1"
call.respondText { }
visionManager.encodeToString(visionOfNumassRepository) title("Numass Data Viewer")
link {
href = "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel = "stylesheet"
attributes["integrity"] =
"sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
attributes["crossorigin"] = "anonymous"
}
} }
} body {
div {
get("/sets/{name...}") { id = "application"
val setName: Name? = call.parameters.getAll("name") }
?.map { NameToken.parse(it) }?.let(::Name) script {
src = "js/numass-web.js"
if (setName == null) { }
call.respondText(status = HttpStatusCode.BadRequest) { "Set name is empty" } script {
return@get src = "https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
} integrity = "sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
attributes["crossorigin"] = "anonymous"
val set: NumassDirectorySet? = withContext(Dispatchers.IO) { repository[setName]?.await() } }
if (set == null) {
call.respondText(status = HttpStatusCode.NotFound) { "A set with name $setName not found in the repository" }
return@get
}
call.respondText {
visionManager.encodeToString(VisionOfNumassSet(setName, set))
}
}
get("/points/{name...}") {
val fullName: Name? = call.parameters.getAll("name")
?.map { NameToken.parse(it) }?.let(::Name)
if (fullName == null) {
call.respondText(status = HttpStatusCode.BadRequest) { "Point name is empty" }
return@get
}
val setName = fullName.cutLast()
val set: NumassDirectorySet? = withContext(Dispatchers.IO) { repository[setName]?.await() }
if (set == null) {
call.respondText(status = HttpStatusCode.NotFound) { "A set with name $setName not found in the repository" }
return@get
}
val pointIndex: Int? = fullName.lastOrNull()?.body?.toIntOrNull()
val point: NumassPoint? = set.points.find { it.index == pointIndex }
if (point == null) {
call.respondText(status = HttpStatusCode.NotFound) { "A point with name $setName/$pointIndex not found in the repository" }
return@get
}
call.respondText {
visionManager.encodeToString(point.toVision())
} }
} }
} }
visionServer(numassCommon.visionManager, url)
}.start()
// val server = context.visionManager.serve { get("/repository") {
// header("numass", VisionPage.scriptHeader("js/numass-web.js")) call.respondText {
// page { visionManager.encodeToString(VisionOfNumassRepository(Name.EMPTY, repository))
// div("flex-column") { }
// h1 { +"Visionforge file demo" } }
// vision { visionOfNumass }
// }
// }
// }
server.openInBrowser() get("/sets/{name...}") {
val setName: Name? = call.parameters.getAll("name")
?.map { NameToken.parse(it) }?.let(::Name)
if (setName == null) {
call.respondText(status = HttpStatusCode.BadRequest) { "Set name is empty" }
return@get
}
println("Enter 'exit' to close server") val set: NumassDirectorySet? = withContext(Dispatchers.IO) { repository[setName]?.await() }
while (readLine() != "exit") { if (set == null) {
// call.respondText(status = HttpStatusCode.NotFound) { "A set with name $setName not found in the repository" }
return@get
}
call.respondText {
visionManager.encodeToString(VisionOfNumassSet(setName, set))
}
}
get("/points/{name...}") {
val fullName: Name? = call.parameters.getAll("name")
?.map { NameToken.parse(it) }?.let(::Name)
if (fullName == null) {
call.respondText(status = HttpStatusCode.BadRequest) { "Point name is empty" }
return@get
}
val setName = fullName.cutLast()
val set: NumassDirectorySet? = withContext(Dispatchers.IO) { repository[setName]?.await() }
if (set == null) {
call.respondText(status = HttpStatusCode.NotFound) { "A set with name $setName not found in the repository" }
return@get
}
val pointIndex: Int? = fullName.lastOrNull()?.body?.toIntOrNull()
val point: NumassPoint? = set.points.find { it.index == pointIndex }
if (point == null) {
call.respondText(status = HttpStatusCode.NotFound) { "A point with name $setName/$pointIndex not found in the repository" }
return@get
}
call.respondText {
visionManager.encodeToString(point.toVision())
}
}
} }
//serveVisionData(VisionRoute("/visions", visionManager))
server.close()
} }

View File

@ -15,6 +15,7 @@ pluginManagement {
} }
plugins { plugins {
id("org.jetbrains.compose").version(extra["compose.version"] as String)
id("space.kscience.gradle.project") version toolsVersion id("space.kscience.gradle.project") version toolsVersion
id("space.kscience.gradle.mpp") version toolsVersion id("space.kscience.gradle.mpp") version toolsVersion
id("space.kscience.gradle.jvm") version toolsVersion id("space.kscience.gradle.jvm") version toolsVersion