Remove Ktor client
This commit is contained in:
parent
b5fdc6c4fe
commit
104e8f8f6f
@ -1,7 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("ru.mipt.npm.gradle.project")
|
||||||
// kotlin("multiplatform") version "1.5.30" apply false
|
|
||||||
// kotlin("js") version "1.5.30" apply false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.5.2")
|
val dataforgeVersion by extra("0.5.2")
|
||||||
|
@ -46,6 +46,7 @@ private object RootDecoder {
|
|||||||
private val refCache: List<RefEntry>,
|
private val refCache: List<RefEntry>,
|
||||||
) : KSerializer<T> by tSerializer {
|
) : KSerializer<T> by tSerializer {
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun deserialize(decoder: Decoder): T {
|
override fun deserialize(decoder: Decoder): T {
|
||||||
val input = decoder as JsonDecoder
|
val input = decoder as JsonDecoder
|
||||||
val element = input.decodeJsonElement()
|
val element = input.decodeJsonElement()
|
||||||
|
@ -9,7 +9,7 @@ import org.w3c.files.FileReader
|
|||||||
import org.w3c.files.get
|
import org.w3c.files.get
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.dom.h2
|
import react.dom.h2
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import react.useMemo
|
import react.useMemo
|
||||||
import react.useState
|
import react.useState
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
@ -34,7 +34,7 @@ external interface GDMLAppProps : Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
val GDMLApp = functionComponent<GDMLAppProps>("GDMLApp") { props ->
|
val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
|
||||||
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
||||||
var deferredVision: Deferred<Solid?> by useState {
|
var deferredVision: Deferred<Solid?> by useState {
|
||||||
CompletableDeferred(props.vision)
|
CompletableDeferred(props.vision)
|
||||||
|
@ -3,7 +3,7 @@ import kotlinx.coroutines.isActive
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.plotly.layout
|
import space.kscience.plotly.layout
|
||||||
import space.kscience.plotly.models.Trace
|
import space.kscience.plotly.models.Trace
|
||||||
@ -20,7 +20,7 @@ external interface DemoProps : Props {
|
|||||||
var context: Context
|
var context: Context
|
||||||
}
|
}
|
||||||
|
|
||||||
val GravityDemo = functionComponent<DemoProps> { props ->
|
val GravityDemo = fc<DemoProps> { props ->
|
||||||
val velocityTrace = Trace{
|
val velocityTrace = Trace{
|
||||||
name = "velocity"
|
name = "velocity"
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
|
|||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import react.useEffect
|
import react.useEffect
|
||||||
import react.useRef
|
import react.useRef
|
||||||
import space.kscience.visionforge.markup.VisionOfMarkup
|
import space.kscience.visionforge.markup.VisionOfMarkup
|
||||||
@ -20,7 +20,7 @@ external interface MarkupProps : Props {
|
|||||||
var markup: VisionOfMarkup?
|
var markup: VisionOfMarkup?
|
||||||
}
|
}
|
||||||
|
|
||||||
val Markup = functionComponent<MarkupProps>("Markup") { props ->
|
val Markup = fc<MarkupProps>("Markup") { props ->
|
||||||
val elementRef = useRef<Element>(null)
|
val elementRef = useRef<Element>(null)
|
||||||
|
|
||||||
useEffect(props.markup, elementRef) {
|
useEffect(props.markup, elementRef) {
|
||||||
|
@ -14,7 +14,7 @@ external interface PlotlyProps : Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val Plotly = functionComponent<PlotlyProps>("Plotly") { props ->
|
val Plotly = fc<PlotlyProps>("Plotly") { props ->
|
||||||
val elementRef = useRef<Element>(null)
|
val elementRef = useRef<Element>(null)
|
||||||
|
|
||||||
useEffect(props.plot, elementRef) {
|
useEffect(props.plot, elementRef) {
|
||||||
|
@ -52,8 +52,6 @@ kotlin {
|
|||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":ui:ring"))
|
implementation(project(":ui:ring"))
|
||||||
implementation(npmlibs.ktor.client.js)
|
|
||||||
implementation(npmlibs.ktor.client.serialization)
|
|
||||||
implementation(project(":visionforge-threejs"))
|
implementation(project(":visionforge-threejs"))
|
||||||
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
|
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
package ru.mipt.npm.muon.monitor
|
package ru.mipt.npm.muon.monitor
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
import kotlinx.browser.window
|
||||||
import io.ktor.client.request.get
|
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.await
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.w3c.fetch.RequestInit
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.button
|
import react.dom.button
|
||||||
import react.dom.p
|
import react.dom.p
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import react.useMemo
|
import react.useMemo
|
||||||
import react.useState
|
import react.useState
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
@ -31,13 +33,12 @@ import kotlin.math.PI
|
|||||||
external interface MMAppProps : Props {
|
external interface MMAppProps : Props {
|
||||||
var model: Model
|
var model: Model
|
||||||
var context: Context
|
var context: Context
|
||||||
var connection: HttpClient
|
|
||||||
var selected: Name?
|
var selected: Name?
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
@JsExport
|
@JsExport
|
||||||
val MMApp = functionComponent<MMAppProps>("Muon monitor") { props ->
|
val MMApp = fc<MMAppProps>("Muon monitor") { props ->
|
||||||
|
|
||||||
val mmOptions = useMemo {
|
val mmOptions = useMemo {
|
||||||
Canvas3DOptions {
|
Canvas3DOptions {
|
||||||
@ -75,9 +76,21 @@ val MMApp = functionComponent<MMAppProps>("Muon monitor") { props ->
|
|||||||
attrs {
|
attrs {
|
||||||
onClickFunction = {
|
onClickFunction = {
|
||||||
context.launch {
|
context.launch {
|
||||||
val event = props.connection.get<Event>(
|
// val event = props.connection.get<Event>(
|
||||||
"http://localhost:8080/event"
|
// "http://localhost:8080/event"
|
||||||
)
|
// )
|
||||||
|
val event = window.fetch(
|
||||||
|
"http://localhost:8080/event",
|
||||||
|
RequestInit("GET")
|
||||||
|
).then { response ->
|
||||||
|
if (response.ok) {
|
||||||
|
response.text()
|
||||||
|
} else {
|
||||||
|
error("Failed to get event")
|
||||||
|
}
|
||||||
|
}.then { body ->
|
||||||
|
Json.decodeFromString(Event.serializer(), body)
|
||||||
|
}.await()
|
||||||
events = events + event
|
events = events + event
|
||||||
props.model.displayEvent(event)
|
props.model.displayEvent(event)
|
||||||
}
|
}
|
||||||
@ -102,7 +115,7 @@ val MMApp = functionComponent<MMAppProps>("Muon monitor") { props ->
|
|||||||
}
|
}
|
||||||
+" : "
|
+" : "
|
||||||
styledSpan {
|
styledSpan {
|
||||||
css{
|
css {
|
||||||
color = Color.blue
|
color = Color.blue
|
||||||
}
|
}
|
||||||
+event.hits.toString()
|
+event.hits.toString()
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package ru.mipt.npm.muon.monitor
|
package ru.mipt.npm.muon.monitor
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import io.ktor.client.features.json.JsonFeature
|
|
||||||
import io.ktor.client.features.json.serializer.KotlinxSerializer
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import react.child
|
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.fetch
|
import space.kscience.dataforge.context.fetch
|
||||||
@ -15,15 +11,9 @@ import space.kscience.visionforge.startApplication
|
|||||||
|
|
||||||
private class MMDemoApp : Application {
|
private class MMDemoApp : Application {
|
||||||
|
|
||||||
private val connection = HttpClient {
|
|
||||||
install(JsonFeature) {
|
|
||||||
serializer = KotlinxSerializer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun start(state: Map<String, Any>) {
|
override fun start(state: Map<String, Any>) {
|
||||||
|
|
||||||
val context = Context("MM-demo"){
|
val context = Context("MM-demo") {
|
||||||
plugin(ThreePlugin)
|
plugin(ThreePlugin)
|
||||||
}
|
}
|
||||||
val visionManager = context.fetch(VisionManager)
|
val visionManager = context.fetch(VisionManager)
|
||||||
@ -35,7 +25,6 @@ private class MMDemoApp : Application {
|
|||||||
child(MMApp) {
|
child(MMApp) {
|
||||||
attrs {
|
attrs {
|
||||||
this.model = model
|
this.model = model
|
||||||
this.connection = this@MMDemoApp.connection
|
|
||||||
this.context = context
|
this.context = context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.show()
|
server.openInBrowser()
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -9,12 +9,12 @@ import kotlinx.html.js.onClickFunction
|
|||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import org.w3c.files.Blob
|
import org.w3c.files.Blob
|
||||||
import org.w3c.files.BlobPropertyBag
|
import org.w3c.files.BlobPropertyBag
|
||||||
import react.FunctionComponent
|
import react.FC
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.button
|
import react.dom.button
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import space.kscience.dataforge.meta.withDefault
|
import space.kscience.dataforge.meta.withDefault
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.encodeToString
|
import space.kscience.visionforge.encodeToString
|
||||||
@ -47,7 +47,7 @@ public external interface CanvasControlsProps : Props {
|
|||||||
public var vision: Vision?
|
public var vision: Vision?
|
||||||
}
|
}
|
||||||
|
|
||||||
public val CanvasControls: FunctionComponent<CanvasControlsProps> = functionComponent("CanvasControls") { props ->
|
public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
|
||||||
flexColumn {
|
flexColumn {
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
|
@ -18,7 +18,7 @@ public external interface TabProps : PropsWithChildren {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val Tab: FunctionComponent<TabProps> = functionComponent { props ->
|
public val Tab: FC<TabProps> = fc { props ->
|
||||||
props.children()
|
props.children()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ public external interface TabPaneProps : PropsWithChildren {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val TabPane: FunctionComponent<TabPaneProps> = functionComponent("TabPane") { props ->
|
public val TabPane: FC<TabPaneProps> = fc("TabPane") { props ->
|
||||||
var activeTab: String? by useState(props.activeTab)
|
var activeTab: String? by useState(props.activeTab)
|
||||||
|
|
||||||
val children: Array<out ReactElement?> = Children.map(props.children) {
|
val children: Array<out ReactElement?> = Children.map(props.children) {
|
||||||
|
@ -2,11 +2,11 @@ package space.kscience.visionforge.bootstrap
|
|||||||
|
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.css.properties.border
|
import kotlinx.css.properties.border
|
||||||
import react.FunctionComponent
|
import react.FC
|
||||||
import react.PropsWithChildren
|
import react.PropsWithChildren
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.h2
|
import react.dom.h2
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
@ -24,7 +24,7 @@ public external interface ThreeControlsProps : PropsWithChildren {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeControls: FunctionComponent<ThreeControlsProps> = functionComponent { props ->
|
public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
|
||||||
tabPane(if (props.selected != null) "Properties" else null) {
|
tabPane(if (props.selected != null) "Properties" else null) {
|
||||||
tab("Canvas") {
|
tab("Canvas") {
|
||||||
card("Canvas configuration") {
|
card("Canvas configuration") {
|
||||||
|
@ -42,7 +42,7 @@ public external interface MetaViewerProps : Props {
|
|||||||
public var descriptor: MetaDescriptor?
|
public var descriptor: MetaDescriptor?
|
||||||
}
|
}
|
||||||
|
|
||||||
private val MetaViewerItem: FunctionComponent<MetaViewerProps> = functionComponent("MetaViewerItem") { props ->
|
private val MetaViewerItem: FC<MetaViewerProps> = fc("MetaViewerItem") { props ->
|
||||||
metaViewerItem(props)
|
metaViewerItem(props)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ private fun RBuilder.metaViewerItem(props: MetaViewerProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val MetaViewer: FunctionComponent<MetaViewerProps> = functionComponent("MetaViewer") { props ->
|
public val MetaViewer: FC<MetaViewerProps> = fc("MetaViewer") { props ->
|
||||||
child(MetaViewerItem) {
|
child(MetaViewerItem) {
|
||||||
attrs {
|
attrs {
|
||||||
this.key = ""
|
this.key = ""
|
||||||
|
@ -76,110 +76,109 @@ public fun RBuilder.nameCrumbs(name: Name?, link: (Name) -> Unit): Unit = styled
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsProps> =
|
public val ThreeCanvasWithControls: FC<ThreeCanvasWithControlsProps> = fc("ThreeViewWithControls") { props ->
|
||||||
functionComponent("ThreeViewWithControls") { props ->
|
var selected by useState { props.selected }
|
||||||
var selected by useState { props.selected }
|
var solid: Solid? by useState(null)
|
||||||
var solid: Solid? by useState(null)
|
|
||||||
|
|
||||||
useEffect {
|
useEffect {
|
||||||
props.context.launch {
|
props.context.launch {
|
||||||
solid = props.builderOfSolid.await().also {
|
solid = props.builderOfSolid.await().also {
|
||||||
it?.root(props.context.visionManager)
|
it?.root(props.context.visionManager)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
|
||||||
selected = it
|
|
||||||
}
|
|
||||||
|
|
||||||
val options = useMemo(props.options) {
|
|
||||||
(props.options?: Canvas3DOptions()).apply {
|
|
||||||
this.onSelect = onSelect
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val selectedVision: Vision? = useMemo(props.builderOfSolid, selected) {
|
|
||||||
selected?.let {
|
|
||||||
when {
|
|
||||||
it.isEmpty() -> solid
|
|
||||||
else -> (solid as? VisionGroup)?.get(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
flexRow {
|
|
||||||
css {
|
|
||||||
height = 100.pct
|
|
||||||
width = 100.pct
|
|
||||||
flexWrap = FlexWrap.wrap
|
|
||||||
alignItems = Align.stretch
|
|
||||||
alignContent = Align.stretch
|
|
||||||
}
|
|
||||||
|
|
||||||
flexColumn {
|
|
||||||
css {
|
|
||||||
height = 100.pct
|
|
||||||
minWidth = 600.px
|
|
||||||
flex(10.0, 1.0, FlexBasis("600px"))
|
|
||||||
position = Position.relative
|
|
||||||
}
|
|
||||||
|
|
||||||
if (solid == null) {
|
|
||||||
LoaderScreen {
|
|
||||||
attrs {
|
|
||||||
message = "Loading Three vision"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
child(ThreeCanvasComponent) {
|
|
||||||
attrs {
|
|
||||||
this.context = props.context
|
|
||||||
this.solid = solid
|
|
||||||
this.selected = selected
|
|
||||||
this.options = options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedVision?.let { vision ->
|
|
||||||
styledDiv {
|
|
||||||
css {
|
|
||||||
position = Position.absolute
|
|
||||||
top = 5.px
|
|
||||||
right = 5.px
|
|
||||||
width = 450.px
|
|
||||||
}
|
|
||||||
Island {
|
|
||||||
IslandHeader {
|
|
||||||
attrs {
|
|
||||||
border = true
|
|
||||||
}
|
|
||||||
nameCrumbs(selected) { selected = it }
|
|
||||||
}
|
|
||||||
IslandContent {
|
|
||||||
propertyEditor(
|
|
||||||
ownProperties = vision.meta,
|
|
||||||
allProperties = vision.computeProperties(),
|
|
||||||
descriptor = vision.descriptor,
|
|
||||||
key = selected
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flexColumn {
|
|
||||||
css {
|
|
||||||
padding(4.px)
|
|
||||||
minWidth = 400.px
|
|
||||||
height = 100.pct
|
|
||||||
overflowY = Overflow.auto
|
|
||||||
flex(1.0, 10.0, FlexBasis("300px"))
|
|
||||||
}
|
|
||||||
ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val onSelect: (Name?) -> Unit = {
|
||||||
|
selected = it
|
||||||
|
}
|
||||||
|
|
||||||
|
val options = useMemo(props.options) {
|
||||||
|
(props.options ?: Canvas3DOptions()).apply {
|
||||||
|
this.onSelect = onSelect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val selectedVision: Vision? = useMemo(props.builderOfSolid, selected) {
|
||||||
|
selected?.let {
|
||||||
|
when {
|
||||||
|
it.isEmpty() -> solid
|
||||||
|
else -> (solid as? VisionGroup)?.get(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
flexRow {
|
||||||
|
css {
|
||||||
|
height = 100.pct
|
||||||
|
width = 100.pct
|
||||||
|
flexWrap = FlexWrap.wrap
|
||||||
|
alignItems = Align.stretch
|
||||||
|
alignContent = Align.stretch
|
||||||
|
}
|
||||||
|
|
||||||
|
flexColumn {
|
||||||
|
css {
|
||||||
|
height = 100.pct
|
||||||
|
minWidth = 600.px
|
||||||
|
flex(10.0, 1.0, FlexBasis("600px"))
|
||||||
|
position = Position.relative
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solid == null) {
|
||||||
|
LoaderScreen {
|
||||||
|
attrs {
|
||||||
|
message = "Loading Three vision"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
child(ThreeCanvasComponent) {
|
||||||
|
attrs {
|
||||||
|
this.context = props.context
|
||||||
|
this.solid = solid
|
||||||
|
this.selected = selected
|
||||||
|
this.options = options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedVision?.let { vision ->
|
||||||
|
styledDiv {
|
||||||
|
css {
|
||||||
|
position = Position.absolute
|
||||||
|
top = 5.px
|
||||||
|
right = 5.px
|
||||||
|
width = 450.px
|
||||||
|
}
|
||||||
|
Island {
|
||||||
|
IslandHeader {
|
||||||
|
attrs {
|
||||||
|
border = true
|
||||||
|
}
|
||||||
|
nameCrumbs(selected) { selected = it }
|
||||||
|
}
|
||||||
|
IslandContent {
|
||||||
|
propertyEditor(
|
||||||
|
ownProperties = vision.meta,
|
||||||
|
allProperties = vision.computeProperties(),
|
||||||
|
descriptor = vision.descriptor,
|
||||||
|
key = selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flexColumn {
|
||||||
|
css {
|
||||||
|
padding(4.px)
|
||||||
|
minWidth = 400.px
|
||||||
|
height = 100.pct
|
||||||
|
overflowY = Overflow.auto
|
||||||
|
flex(1.0, 10.0, FlexBasis("300px"))
|
||||||
|
}
|
||||||
|
ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,12 @@ import kotlinx.html.js.onClickFunction
|
|||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import org.w3c.files.Blob
|
import org.w3c.files.Blob
|
||||||
import org.w3c.files.BlobPropertyBag
|
import org.w3c.files.BlobPropertyBag
|
||||||
import react.FunctionComponent
|
import react.FC
|
||||||
import react.Props
|
import react.Props
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.button
|
import react.dom.button
|
||||||
import react.functionComponent
|
import react.fc
|
||||||
import ringui.Island
|
import ringui.Island
|
||||||
import ringui.SmartTabs
|
import ringui.SmartTabs
|
||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
@ -52,7 +52,7 @@ internal external interface CanvasControlsProps : Props {
|
|||||||
public var vision: Vision?
|
public var vision: Vision?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val CanvasControls: FunctionComponent<CanvasControlsProps> = functionComponent("CanvasControls") { props ->
|
internal val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { props ->
|
||||||
flexColumn {
|
flexColumn {
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
@ -94,7 +94,7 @@ public external interface ThreeControlsProps : Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeControls: FunctionComponent<ThreeControlsProps> = functionComponent { props ->
|
public val ThreeControls: FC<ThreeControlsProps> = fc { props ->
|
||||||
SmartTabs("Tree") {
|
SmartTabs("Tree") {
|
||||||
props.vision?.let {
|
props.vision?.let {
|
||||||
Tab("Tree") {
|
Tab("Tree") {
|
||||||
|
@ -15,7 +15,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("space.kscience:dataforge-context:$dataforgeVersion")
|
api("space.kscience:dataforge-context:$dataforgeVersion")
|
||||||
api("org.jetbrains.kotlinx:kotlinx-html:${ru.mipt.npm.gradle.KScienceVersions.htmlVersion}")
|
api(npmlibs.kotlinx.html)
|
||||||
api("org.jetbrains.kotlin-wrappers:kotlin-css")
|
api("org.jetbrains.kotlin-wrappers:kotlin-css")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,9 @@ plugins {
|
|||||||
id("ru.mipt.npm.gradle.jvm")
|
id("ru.mipt.npm.gradle.jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktorVersion = ru.mipt.npm.gradle.KScienceVersions.ktorVersion
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":visionforge-core"))
|
api(project(":visionforge-core"))
|
||||||
api("io.ktor:ktor-server-cio:$ktorVersion")
|
api(npmlibs.ktor.server.cio)
|
||||||
//api("io.ktor:ktor-server-netty:$ktorVersion")
|
api(npmlibs.ktor.html.builder)
|
||||||
api("io.ktor:ktor-html-builder:$ktorVersion")
|
api(npmlibs.ktor.websockets)
|
||||||
api("io.ktor:ktor-websockets:$ktorVersion")
|
|
||||||
}
|
}
|
@ -38,10 +38,7 @@ import space.kscience.visionforge.html.*
|
|||||||
import space.kscience.visionforge.three.server.VisionServer.Companion.DEFAULT_PAGE
|
import space.kscience.visionforge.three.server.VisionServer.Companion.DEFAULT_PAGE
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import kotlin.collections.set
|
|
||||||
import kotlin.time.Duration
|
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlin.time.ExperimentalTime
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,10 +50,30 @@ public class VisionServer internal constructor(
|
|||||||
private val rootRoute: String,
|
private val rootRoute: String,
|
||||||
) : Configurable, CoroutineScope by application {
|
) : Configurable, CoroutineScope by application {
|
||||||
override val meta: ObservableMutableMeta = MutableMeta()
|
override val meta: ObservableMutableMeta = MutableMeta()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update minimal interval between updates in milliseconds (if there are no updates, push will not happen
|
||||||
|
*/
|
||||||
public var updateInterval: Long by meta.long(300, key = UPDATE_INTERVAL_KEY)
|
public var updateInterval: Long by meta.long(300, key = UPDATE_INTERVAL_KEY)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache page fragments. If false, pages will be reconstructed on each call. Default: `true`
|
||||||
|
*/
|
||||||
public var cacheFragments: Boolean by meta.boolean(true)
|
public var cacheFragments: Boolean by meta.boolean(true)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embed the initial state of the vision inside its html tag. Default: `true`
|
||||||
|
*/
|
||||||
public var dataEmbed: Boolean by meta.boolean(true, Name.parse("data.embed"))
|
public var dataEmbed: Boolean by meta.boolean(true, Name.parse("data.embed"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch data on vision load. Overrides embedded data. Default: `false`
|
||||||
|
*/
|
||||||
public var dataFetch: Boolean by meta.boolean(false, Name.parse("data.fetch"))
|
public var dataFetch: Boolean by meta.boolean(false, Name.parse("data.fetch"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to server to get pushes. The address of the server is embedded in the tag. Default: `true`
|
||||||
|
*/
|
||||||
public var dataConnect: Boolean by meta.boolean(true, Name.parse("data.connect"))
|
public var dataConnect: Boolean by meta.boolean(true, Name.parse("data.connect"))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +81,9 @@ public class VisionServer internal constructor(
|
|||||||
*/
|
*/
|
||||||
private val globalHeaders: ArrayList<HtmlFragment> = ArrayList()
|
private val globalHeaders: ArrayList<HtmlFragment> = ArrayList()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a header to all pages produced by this server
|
||||||
|
*/
|
||||||
public fun header(block: TagConsumer<*>.() -> Unit) {
|
public fun header(block: TagConsumer<*>.() -> Unit) {
|
||||||
globalHeaders.add(block)
|
globalHeaders.add(block)
|
||||||
}
|
}
|
||||||
@ -73,7 +93,7 @@ public class VisionServer internal constructor(
|
|||||||
headers: List<HtmlFragment>,
|
headers: List<HtmlFragment>,
|
||||||
visionFragment: HtmlVisionFragment,
|
visionFragment: HtmlVisionFragment,
|
||||||
): Map<Name, Vision> {
|
): Map<Name, Vision> {
|
||||||
var visionMap: Map<Name,Vision>? = null
|
var visionMap: Map<Name, Vision>? = null
|
||||||
|
|
||||||
head {
|
head {
|
||||||
meta {
|
meta {
|
||||||
@ -102,7 +122,7 @@ public class VisionServer internal constructor(
|
|||||||
* Server a map of visions without providing explicit html page for them
|
* Server a map of visions without providing explicit html page for them
|
||||||
*/
|
*/
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
public fun serveVisions(route: Route, visions: Map<Name, Vision>): Unit = route {
|
internal fun serveVisions(route: Route, visions: Map<Name, Vision>): Unit = route {
|
||||||
application.log.info("Serving visions $visions at $route")
|
application.log.info("Serving visions $visions at $route")
|
||||||
|
|
||||||
//Update websocket
|
//Update websocket
|
||||||
@ -158,8 +178,13 @@ public class VisionServer internal constructor(
|
|||||||
* Create a static html page and serve visions produced in the process
|
* Create a static html page and serve visions produced in the process
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public fun createHtmlAndServe(route: String, title: String, headers: List<HtmlFragment>, visionFragment: HtmlVisionFragment): String{
|
public fun createHtmlAndServe(
|
||||||
val htmlString = createHTML().apply {
|
route: String,
|
||||||
|
title: String,
|
||||||
|
headers: List<HtmlFragment>,
|
||||||
|
visionFragment: HtmlVisionFragment,
|
||||||
|
): String {
|
||||||
|
val htmlString = createHTML().apply {
|
||||||
html {
|
html {
|
||||||
visionPage(title, headers, visionFragment).also {
|
visionPage(title, headers, visionFragment).also {
|
||||||
serveVisions(route, it)
|
serveVisions(route, it)
|
||||||
@ -171,7 +196,7 @@ public class VisionServer internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serv visions in a given [route] without providing a page template
|
* Serve visions in a given [route] without providing a page template
|
||||||
*/
|
*/
|
||||||
public fun serveVisions(route: String, visions: Map<Name, Vision>): Unit {
|
public fun serveVisions(route: String, visions: Map<Name, Vision>): Unit {
|
||||||
application.routing {
|
application.routing {
|
||||||
@ -245,6 +270,9 @@ public inline fun VisionServer.useScript(src: String, crossinline block: SCRIPT.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use css with given stylesheet link as a global header for all pages.
|
||||||
|
*/
|
||||||
public inline fun VisionServer.useCss(href: String, crossinline block: LINK.() -> Unit = {}) {
|
public inline fun VisionServer.useCss(href: String, crossinline block: LINK.() -> Unit = {}) {
|
||||||
header {
|
header {
|
||||||
link {
|
link {
|
||||||
@ -256,7 +284,7 @@ public inline fun VisionServer.useCss(href: String, crossinline block: LINK.() -
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach plotly application to given server
|
* Attach VisionForge server application to given server
|
||||||
*/
|
*/
|
||||||
public fun Application.visionServer(context: Context, route: String = DEFAULT_PAGE): VisionServer {
|
public fun Application.visionServer(context: Context, route: String = DEFAULT_PAGE): VisionServer {
|
||||||
if (featureOrNull(WebSockets) == null) {
|
if (featureOrNull(WebSockets) == null) {
|
||||||
@ -286,6 +314,9 @@ public fun Application.visionServer(context: Context, route: String = DEFAULT_PA
|
|||||||
return VisionServer(visionManager, this, route)
|
return VisionServer(visionManager, this, route)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a stand-alone VisionForge server at given host/port
|
||||||
|
*/
|
||||||
public fun VisionManager.serve(
|
public fun VisionManager.serve(
|
||||||
host: String = "localhost",
|
host: String = "localhost",
|
||||||
port: Int = 7777,
|
port: Int = 7777,
|
||||||
@ -294,10 +325,16 @@ public fun VisionManager.serve(
|
|||||||
visionServer(context).apply(block)
|
visionServer(context).apply(block)
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
public fun ApplicationEngine.show() {
|
/**
|
||||||
|
* Connect to a given Ktor server using browser
|
||||||
|
*/
|
||||||
|
public fun ApplicationEngine.openInBrowser() {
|
||||||
val connector = environment.connectors.first()
|
val connector = environment.connectors.first()
|
||||||
val uri = URI("http", null, connector.host, connector.port, null, null, null)
|
val uri = URI("http", null, connector.host, connector.port, null, null, null)
|
||||||
Desktop.getDesktop().browse(uri)
|
Desktop.getDesktop().browse(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the server with default timeouts
|
||||||
|
*/
|
||||||
public fun ApplicationEngine.close(): Unit = stop(1000, 5000)
|
public fun ApplicationEngine.close(): Unit = stop(1000, 5000)
|
Loading…
Reference in New Issue
Block a user