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 tablesVersion: String by extra("0.2.0-dev-3")
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{

View File

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

View File

@ -1,5 +1,6 @@
plugins {
id("space.kscience.gradle.mpp")
id("org.jetbrains.compose")
`maven-publish`
}
@ -28,7 +29,14 @@ kotlin {
jvmMain {
dependencies {
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)
}
override fun render(element: Element, vision: Vision, meta: Meta) {
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
when (vision) {
is VisionOfNumassHv -> element.append {
h1 { +"HV" }
@ -64,7 +64,7 @@ public class NumassJsPlugin : AbstractPlugin(), ElementVisionRenderer {
vision.spectra.forEach { (channel, spectrum) ->
val pairs = spectrum.entries.sortedBy { it.key }
scatter {
name = channel
this.name = channel
mode = ScatterMode.lines
line {
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
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.cio.CIO
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.routing.get
import io.ktor.server.routing.routing
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.html.*
import ru.inr.mass.data.api.NumassPoint
import ru.inr.mass.data.proto.NumassDirectorySet
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.cutLast
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") {
plugin(NumassProtoPlugin)
plugin(NumassCommonPlugin)
@ -40,93 +47,98 @@ public suspend fun main() {
val repositroyName = "D:\\Work\\Numass\\data\\test"
val port = 7777
val host = "localhost"
val repository: DataTree<NumassDirectorySet> = runBlocking { numassProto.readRepository(repositroyName) }
val url = URLBuilder(host = host, port = port).build()
routing {
resources()
val repository: DataTree<NumassDirectorySet> = numassProto.readRepository(repositroyName)
val visionOfNumassRepository = VisionOfNumassRepository(Name.EMPTY, repository)
val server = context.embeddedServer(CIO, port, host) {
routing {
get("/repository") {
call.respondText {
visionManager.encodeToString(visionOfNumassRepository)
get("/") {
call.respondHtml {
head {
meta { charset = "utf-8" }
meta {
name = "viewport"
content = "width=device-width, initial-scale=1"
}
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"
}
}
}
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
}
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())
body {
div {
id = "application"
}
script {
src = "js/numass-web.js"
}
script {
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"
}
}
}
}
visionServer(numassCommon.visionManager, url)
}.start()
// val server = context.visionManager.serve {
// header("numass", VisionPage.scriptHeader("js/numass-web.js"))
// page {
// div("flex-column") {
// h1 { +"Visionforge file demo" }
// vision { visionOfNumass }
// }
// }
// }
get("/repository") {
call.respondText {
visionManager.encodeToString(VisionOfNumassRepository(Name.EMPTY, repository))
}
}
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")
while (readLine() != "exit") {
//
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())
}
}
}
server.close()
//serveVisionData(VisionRoute("/visions", visionManager))
}

View File

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