Working on data viewer UI
This commit is contained in:
parent
7efb952163
commit
e95f73d94d
@ -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{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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") }) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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()
|
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user